<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  
  
  <title>Hexo</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <meta property="og:type" content="website">
<meta property="og:title" content="Hexo">
<meta property="og:url" content="https://chudod.gitee.io/myworks/index.html">
<meta property="og:site_name" content="Hexo">
<meta property="og:locale" content="en_US">
<meta property="article:author" content="John Doe">
<meta name="twitter:card" content="summary">
  
    <link rel="alternate" href="/myworks/atom.xml" title="Hexo" type="application/atom+xml">
  
  
    <link rel="shortcut icon" href="/myworks/favicon.png">
  
  
    
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/typeface-source-code-pro@0.0.71/index.min.css">

  
  
<link rel="stylesheet" href="/myworks/css/style.css">

  
    
<link rel="stylesheet" href="/myworks/fancybox/jquery.fancybox.min.css">

  
<meta name="generator" content="Hexo 6.2.0"></head>

<body>
  <div id="container">
    <div id="wrap">
      <header id="header">
  <div id="banner"></div>
  <div id="header-outer" class="outer">
    <div id="header-title" class="inner">
      <h1 id="logo-wrap">
        <a href="/myworks/" id="logo">Hexo</a>
      </h1>
      
    </div>
    <div id="header-inner" class="inner">
      <nav id="main-nav">
        <a id="main-nav-toggle" class="nav-icon"></a>
        
          <a class="main-nav-link" href="/myworks/">Home</a>
        
          <a class="main-nav-link" href="/myworks/archives">Archives</a>
        
      </nav>
      <nav id="sub-nav">
        
          <a id="nav-rss-link" class="nav-icon" href="/myworks/atom.xml" title="RSS Feed"></a>
        
        <a id="nav-search-btn" class="nav-icon" title="Search"></a>
      </nav>
      <div id="search-form-wrap">
        <form action="//google.com/search" method="get" accept-charset="UTF-8" class="search-form"><input type="search" name="q" class="search-form-input" placeholder="Search"><button type="submit" class="search-form-submit">&#xF002;</button><input type="hidden" name="sitesearch" value="https://chudod.gitee.io/myworks"></form>
      </div>
    </div>
  </div>
</header>

      <div class="outer">
        <section id="main">
  
    <article id="post-Russian_Grammar" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/myworks/2022/05/24/Russian_Grammar/" class="article-date">
  <time class="dt-published" datetime="2022-05-23T16:00:00.000Z" itemprop="datePublished">2022-05-24</time>
</a>
    
  <div class="article-category">
    <a class="article-category-link" href="/myworks/categories/%D0%A0%D0%BE%D1%81%D1%81%D0%B8%D1%8F/">Россия</a>
  </div>

  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="p-name article-title" href="/myworks/2022/05/24/Russian_Grammar/">Русская Граммаатика(俄语语法)</a>
    </h1>
  

      </header>
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h1 id="名词变格"><a href="#名词变格" class="headerlink" title="名词变格"></a>名词变格</h1><h2 id="单数第四格"><a href="#单数第四格" class="headerlink" title="单数第四格"></a>单数第四格</h2><h3 id="变化形式"><a href="#变化形式" class="headerlink" title="变化形式"></a>变化形式</h3><head>
    <meta charset="utf-8">
<h4 align="center">名词单数第四格</h4>
<table align="center" border="1" width="700px" cellspacing="7">
<tr>
    <td style="border: 1px solid black" colspan="2" align="center"></td>
    <td style="border: 1px solid black" align="center">第一格</td>
    <td style="border: 1px solid black" align="center">第二格</td>
    <td style="border: 1px solid black" align="center">第四格</td>
    <td style="border: 1px solid black" align="center">记忆</td>
</tr>
<tr>
    <td style="border: 1px solid black" rowspan="2" align="center">阳性</td>
    <td style="border: 1px solid black" align="center">非动物</td>
    <td style="border: 1px solid black" align="center">фильм<br>музей<br>портфель<br></td>
    <td style="border: 1px solid black" align="center">фильма<br>музея<br>портфеля<br></td>
    <td style="border: 1px solid black" align="center">фильм<br>музей<br>портфель<br></td>
    <td style="border: 1px solid black" align="center">第四格与第一格相同
    </td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">动物</td>
    <td style="border: 1px solid black" align="center">студент<br>герой<br>учитель<br></td>
    <td style="border: 1px solid black" align="center">студента<br>героя<br>учителя<br></td>
    <td style="border: 1px solid black" align="center">студента<br>героя<br>учителя<br></td>
    <td style="border: 1px solid black" align="center">第四格与第二格相同
    </td>
</tr>
<tr>
    <td style="border: 1px solid black"  align="center">阴性</td>
    <td style="border: 1px solid black" align="center">所有名词（动物和非动物）</td>
    <td style="border: 1px solid black" align="center">школа<br>сестра<br>кухния<br>
    тётя<br>тетрадь<br>дочь<br></td>
    <td style="border: 1px solid black" align="center">школы<br>сестры<br>кухни<br>
    тёти<br>тетради<br>дочи<br></td>
    <td style="border: 1px solid black" align="center">школу<br>сестру<br>кухню<br>
    тётю<br>тетрадь<br>дочь<br></td>
    <td style="border: 1px solid black" align="center">第一、二、四格各异<br>第四格变化：-а变-у，-я变ю, -ь不变
    </td>
</tr>
</table>

<h3 id="用法"><a href="#用法" class="headerlink" title="用法"></a>用法</h3><p>1、Я хорошо знаю <strong>учителя Чжана</strong>.     我很认识张老师。<br>2、Анан очен любит <strong>сына Виктора</strong> и <strong>дочь Нину</strong>.    安娜非常喜欢儿子维克多和女儿妮娜。</p>
<h1 id="过去式"><a href="#过去式" class="headerlink" title="过去式"></a>过去式</h1><head>
    <meta charset="utf-8">
<h4 align="center">名词单数第四格</h4>
<table align="center" border="1" width="700px" cellspacing="7">
<tr>
    <td style="border: 1px solid black" colspan="3" align="center">人称代词</td>
    <td style="border: 1px solid black" align="center">быть</td>
    <td style="border: 1px solid black" align="center">说明</td>
</tr>
<tr>
    <td style="border: 1px solid black" rowspan="3" align="center">单数</td>
    <td style="border: 1px solid black" align="center">阳</td>
    <td style="border: 1px solid black" align="center">он</td>
    <td style="border: 1px solid black" align="center">был</td>
    <td style="border: 1px solid black" rowspan="4" align="center"></td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">阴</td>
    <td style="border: 1px solid black" align="center">она</td>
    <td style="border: 1px solid black" align="center">была</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">中</td>
    <td style="border: 1px solid black" align="center">оно</td>
    <td style="border: 1px solid black" align="center">было</td>
</tr>
<tr>
    <td style="border: 1px solid black" colspan="2" align="center">复数</td>
    <td style="border: 1px solid black" align="center">они</td>
    <td style="border: 1px solid black" align="center">были</td>
</tr>
</table>

<head>
    <meta charset="utf-8">
<h4 align="center">带-ся动词过去式的结尾变化</h4>
<table align="center" border="0" width="700px" cellspacing="7">
<tr>
    <td align="center">（阳）</td>
    <td align="center">（阴）</td>
    <td align="center">（中）</td>
    <td align="center">（复）</td>
</tr>
</table>
      
    </div>
    <footer class="article-footer">
      <a data-url="https://chudod.gitee.io/myworks/2022/05/24/Russian_Grammar/" data-id="cl3kznr08000xj0uk7pra4o5e" data-title="Русская Граммаатика(俄语语法)" class="article-share-link">Share</a>
      
      
      
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/myworks/tags/%D0%A0%D0%BE%D1%81%D1%81%D0%B8%D1%8F/" rel="tag">Россия</a></li></ul>

    </footer>
  </div>
  
</article>



  
    <article id="post-OS_FileSystem" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/myworks/2022/05/18/OS_FileSystem/" class="article-date">
  <time class="dt-published" datetime="2022-05-17T16:00:00.000Z" itemprop="datePublished">2022-05-18</time>
</a>
    
  <div class="article-category">
    <a class="article-category-link" href="/myworks/categories/%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/">计算机基础知识</a>►<a class="article-category-link" href="/myworks/categories/%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/">操作系统</a>
  </div>

  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="p-name article-title" href="/myworks/2022/05/18/OS_FileSystem/">文件系统概念和Ext2文件系统</a>
    </h1>
  

      </header>
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h1 id="文件系统概念"><a href="#文件系统概念" class="headerlink" title="文件系统概念"></a>文件系统概念</h1><p>我在本科第一次学习“文件系统”时，觉得这一章的很多概念仿佛如空中楼阁，因为“文件系统”太抽象了，后来才慢慢加深理解，其实文件系统就是磁盘管理，也可以说文件系统是物理设备的高级抽象。硬盘（低速设备）读写单位是扇区，通常为512 Bytes，而文件系统的读写单位是块（若干个扇区组成，为了避免频繁访问磁盘，一次读入多个块）。为了管理这些块，需要各种数据结构。</p>
<h2 id="inode和文件控制块FCB"><a href="#inode和文件控制块FCB" class="headerlink" title="inode和文件控制块FCB"></a>inode和文件控制块FCB</h2><p>一个文件被拆分成多个块来存储，因此需要一种文件组织方式。以Windows的FAT32为例，FAT是文件分配表(File Allocation Table)，所有的块被用链式结构来组织，在每一块的最后记录下一块的地址，这样文件不需要连续存储，节省了磁盘空间。FAT文件系统为每个文件都分配了一个FAT表，用单独的链式结构来存储、跟踪文件的所有块。FAT文件系统的缺点是文件查找效率地下，为了定位到最后一个数据块，需要遍历前面的所有数据块，且每访问一个块就涉及一次磁盘寻道，使得本就低速的磁盘访问更加频繁，也许微软受不了FAT32文件系统，后来推出了NTFS文件系统(下图来自《操作系统概念》)。</p>
<div style = "align: center">
<img src="https://note.youdao.com/yws/api/personal/file/WEB200ceca287a455a1754af8fc6e802128?method=download&shareKey=69113f8f61e335d1864757cf6d288929" width="40%" height="40%"/>  

<p>Unix的文件系统比较先进，采用索引结构来组织文件块，文件块依然可以零散地分布在磁盘中，但Unix文件系统为每个文件的所有块都建立了一个索引表，索引表就是块地址数组，数组元素就是块的地址，访问任意一个块只需要从索引表获得块地址就可以了，速度大大提升。包含此索引表的索引结构就是index node，简称inode(i节点)。任何一个文件都有一个inode，inode记录了文件的所有信息，包括一个索引表，记录文件所有块的块地址。索引结构的缺点是索引结构本身要占一定的存储空间，文件越大，块越多，索引表越大，因此Unix采取了一个折中的方法，采用多级索引结构：inode的索引表一共15个索引项，如果文件块小于12块，那么将这12块的块地址直接存储在前12个索引项中，这前面12个索引可以直接获得块地址，如果文件大于12块，就用第13个索引（一级索引指针）指向一个新的块，新的一块存储256个块地址（一个块1024字节，一个块地址4字节，所以可以存储256个块地址），因此一级索引结构可以存储12+256&#x3D;268个块。如果文件大于268个块，就建立二级索引指针，因此inode索引表的第14个索引是二级索引指针，，第15个是三级索引指针，这样可以管理非常大的文件（文件最多$12+256+256\times{256}+256\times{256}\times{256}块\approx{16.06G}$，如果一个块1024个字节）。</p>
<div style = "align: center">
<img src="https://note.youdao.com/yws/api/personal/file/WEB5c6be0c67c8d7e412bb46a0fc7dfc4b2?method=download&shareKey=69113f8f61e335d1864757cf6d288929" width="50%" height="50%"/>  

<p>只要用于控制和管理文件相关信息的数据结构都叫文件控制块FCB(File Control Block)，因此inode也是FCB的一种。并且inode的数量等于文件数量，为了方便管理，分区中所有文件的inode都用一个大表格(inode_table)来维护，用单独的几个磁盘块来存储这个表格，再结合inode位图（单独的一块）。表格就是一个数组，数组中的元素就是inode地址，数组的下标就是inode的编号。可以根据inode编号来查询inode地址。Linux中的inode的定义如下（少了3个字段，但是不重要，没贴出来，来自《深入理解Linx内核》）：</p>
<div style = "align: center">
<img src="https://note.youdao.com/yws/api/personal/file/WEB59ac0acfacd302c44a1c25b94075ea37?method=download&shareKey=69113f8f61e335d1864757cf6d288929" width="70%" height="70%"/>  

<h2 id="目录项与目录"><a href="#目录项与目录" class="headerlink" title="目录项与目录"></a>目录项与目录</h2><p>在Unix的inode中，缺少了一个对用户来说至关重要的属性：文件名。用户给出文件名来访问文件，而文件系统通过inode来定位数据块（文件名对文件系统来说不重要，有了inode即可）。因此目录的作用就是将文件名和inode绑定。用户给出文件名，文件在目录项中找到文件名对应的inode，然后再找到数据块。<br>在Linux中，目录和文件都用inode来表示，因此目录也是一种文件。inode同时指向目录和普通文件，磁盘文件系统中没有一种叫做目录的数据结构，磁盘上有的只是inode，inode指向文件实体的数据块，而不关心数据块具体的内容，因此目录和普通文件本质的区别就是“数据块上记录的内容”不同。例如，一个.txt文本文件的数据块记录的是文本文件的ASCII码，而一个目录文件的数据块，记录的内容是目录下包含的所有目录项，如下所示：</p>
<div style = "align: center">
<img src="https://note.youdao.com/yws/api/personal/file/WEB3edb3a5062775e84e27a1b3baf7214d4?method=download&shareKey=69113f8f61e335d1864757cf6d288929" width="70%" height="70%"/>  

<p>其中’.’表示当前目录，’..’表示上一级目录，每一个目录项的字段如下所示：</p>
<div style = "align: center">
<img src="https://note.youdao.com/yws/api/personal/file/WEB8ccdb56ae2d2ddd63d7a13a576d23bb1?method=download&shareKey=69113f8f61e335d1864757cf6d288929" width="70%" height="70%"/> 

<p>目录项长度通常为4的倍数，不足4的倍数会在文件名末尾补上’\0’。可以看到，目录项包含文件对应的inode索引，因此获得这个索引之后，就可以根据该索引值计算出inode地址，然后就可以得到文件的inode了。这一个inode指向的文件也可能是目录文件，因此数据块中包含目录项，这样就可以根据多级目录来查询了。另外，不管是普通文件还是目录文件（这里将目录称之为“目录文件”），总会位于一个目录下，所有普通文件和目录都位于根目录’&#x2F;‘下，根目录是所有目录的父目录。<br>我本科学到这里的时候被绕晕了：要想找到数据块，必须找到文件的inode，而要找到文件的inode，又必须要知道目录项（目录项包含inode索引），而要找到目录项又必须先找到数据块（目录项本身又是目录文件数据块里面的内容）……寻找过程似乎是个死循环。这种看似死循环的过程，原因无外乎就是上层目录是无休止的，因此有个固定的目录就可以了，答案就是根目录’&#x2F;‘！每个分区都有自己的根目录，根目录是所有目录的父目录，在创建文件分区的时候就已经在一个固定死的位置写好了根目录的inode，查找文件时时都首先根据根目录inode获得根目录数据块，然后再查找这个数据块里面的目录项，最后递归查找，找到任意子目录的文件。因此查找&#x2F;home&#x2F;hello.txt文件的过程是：</p>
<ul>
<li>1、文件系统找到根目录’&#x2F;‘的inode</li>
<li>2、由根目录的inode找到根目录的数据块</li>
<li>3、根目录数据块中有home目录项，并由home目录项找到home这个目录文件的inode</li>
<li>5、由home目录文件的inode找到home目录的数据块</li>
<li>6、home目录数据块有hello.txt目录项，并由该目录项找到hollo.txt这个文件的inode</li>
<li>7、由hello.txt文件的inode找到对应的数据块，数据块存储着字符串的ASCII码值。</li>
</ul>
<h2 id="文件系统布局"><a href="#文件系统布局" class="headerlink" title="文件系统布局"></a>文件系统布局</h2><p>Ext2文件系统在磁盘上的布局如下图所示：<br><img src="https://note.youdao.com/yws/api/personal/file/WEB8773c112d52de95d6691bdec4e7ea012?method=download&shareKey=69113f8f61e335d1864757cf6d288929"><br>Ext2文件系统将若干个块分成一个组，一个分区可能有多个块组。</p>
<ul>
<li><p>在整个磁盘中，最开始一个块是引导块，包含引导操作系统的相关信息，MBR(Master Boot Record和Loader程序就在这个块中)。如果该磁盘不包含操作系统，则该块内容为空。NTFS文件系统称该之为分区引导扇区。</p>
</li>
<li><p>每个块组的第一块是超级块，是在为分区创建文件系统时创建的，超级块包含总的inode数量、块的数量、每块的大小（字节）、每组的块数等等这些重要信息，详细字段如下所示：</p>
<div style = "align: center">
<img src="https://note.youdao.com/yws/api/personal/file/WEBb353acd38c3d124728dfb939d9eb1472?method=download&shareKey=69113f8f61e335d1864757cf6d288929" width="70%" height="70%"/> 
</li>
<li><p>组描述符紧跟着超级块，记录着数据块位图从几号块开始、inode位图从几号块开始、inode节点从几号块开始等等信息，具体字段如下：</p>
<div style = "align: center">
<img src="https://note.youdao.com/yws/api/personal/file/WEB4f0be2bb01668eba716ad737927f1217?method=download&shareKey=69113f8f61e335d1864757cf6d288929" width="70%" height="70%"/>
</li>
<li><p>之后是数据块位图和inode位图，记录那些块被（数据块或者inode）使用过了，1比特表示对应的块被使用过了。</p>
</li>
<li><p>索引节点块存储所有inode。</p>
</li>
<li><p>后面的所有块均为存储数据的数据块（存储目录文件、普通文件）</p>
</li>
</ul>
<h2 id="Ext2文件系统实例"><a href="#Ext2文件系统实例" class="headerlink" title="Ext2文件系统实例"></a>Ext2文件系统实例</h2><p>现有一个磁盘had.raw，根目录的内容如下，一共4个文件（包括目录）：</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">.</span><br><span class="line">..</span><br><span class="line">lost+found</span><br><span class="line">hello.txt</span><br></pre></td></tr></table></figure>
<p>利用hexdump命令查看磁盘内容：</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexdump -C rootfs/hda.raw | less</span><br></pre></td></tr></table></figure>
<p>磁盘内容如下，可以根据各个块的字段来查看意义：</p>
<h3 id="超级块"><a href="#超级块" class="headerlink" title="超级块"></a>超级块</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">00000000</span>  <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  |................|</span><br><span class="line">***</span><br><span class="line"><span class="comment">//以上为引导块（0号块），接下来为超级块（1号块）</span></span><br><span class="line"><span class="number">00000400</span>  <span class="number">00</span> <span class="number">01</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">08</span> <span class="number">00</span> <span class="number">00</span>  <span class="number">66</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> cd <span class="number">07</span> <span class="number">00</span> <span class="number">00</span>  |........f.......|</span><br><span class="line">          ^_________^ ^_________^</span><br><span class="line">        s_inodes_count s_blocks_count</span><br><span class="line"><span class="number">00000410</span>  f4 <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">01</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  |................|</span><br><span class="line">                                   ^_________^</span><br><span class="line">                                   s_log_block_size</span><br><span class="line"><span class="number">00000420</span>  <span class="number">00</span> <span class="number">20</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">20</span> <span class="number">00</span> <span class="number">00</span>  <span class="number">00</span> <span class="number">01</span> <span class="number">00</span> <span class="number">00</span> <span class="number">43</span> <span class="number">54</span> <span class="number">9</span>e <span class="number">5</span>e  |. ... ......CT.^|</span><br><span class="line">          ^_________^              ^_________^</span><br><span class="line">          s_blocks_per_group       s_inodes_per_group</span><br><span class="line"><span class="number">00000430</span>  c8 <span class="number">56</span> <span class="number">9</span>e <span class="number">5</span>e <span class="number">00</span> <span class="number">00</span> <span class="number">15</span> <span class="number">00</span>  <span class="number">53</span> ef <span class="number">01</span> <span class="number">00</span> <span class="number">01</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  |.V.^....S.......|</span><br></pre></td></tr></table></figure>

<table>
<thead>
<tr>
<th align="center">字段</th>
<th align="center">值</th>
<th align="center">意义</th>
</tr>
</thead>
<tbody><tr>
<td align="center">s_inodes_count</td>
<td align="center">0x0100</td>
<td align="center">总共包含0x0100个inode</td>
</tr>
<tr>
<td align="center">s_blocks_count</td>
<td align="center">0x0800</td>
<td align="center">总共包含0x0800块</td>
</tr>
<tr>
<td align="center">s_log_block_size</td>
<td align="center">0x0000</td>
<td align="center">块大小为$1024\times{2^0}$，即1024B</td>
</tr>
<tr>
<td align="center">s_blocks_per_group</td>
<td align="center">0x2000</td>
<td align="center">每组包含0x2000块</td>
</tr>
<tr>
<td align="center">s_inodes_per_group</td>
<td align="center">0x0100</td>
<td align="center">每组包含0x0100(256)个inode，占$\frac{256}{8}&#x3D;32$个块</td>
</tr>
</tbody></table>
<p>其中每个inode占128字节，因此一个块包含$\frac{1024}{128}&#x3D;8$个inode。</p>
<h3 id="组描述符"><a href="#组描述符" class="headerlink" title="组描述符"></a>组描述符</h3><p>组描述符紧跟着超级块</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//以下为组描述符（2号块）</span></span><br><span class="line"><span class="number">00000800</span>  <span class="number">03</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">04</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  <span class="number">05</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> cd <span class="number">07</span> f4 <span class="number">00</span>  |................|</span><br><span class="line">          ^_________^ ^_________^  ^_________^</span><br><span class="line">     bg_clock_bitmap bg_inode_bitmap bg_inode_table</span><br><span class="line"><span class="number">00000810</span>  <span class="number">02</span> <span class="number">00</span> <span class="number">04</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  |................|</span><br><span class="line"><span class="number">00000820</span>  <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  |................|</span><br><span class="line">***</span><br></pre></td></tr></table></figure>

<table>
<thead>
<tr>
<th align="center">字段</th>
<th align="center">值</th>
<th align="center">意义</th>
</tr>
</thead>
<tbody><tr>
<td align="center">bg_clock_bitmap</td>
<td align="center">0x03</td>
<td align="center">数据块位图区从3号块开始</td>
</tr>
<tr>
<td align="center">bg_inode_bitmap</td>
<td align="center">0x04</td>
<td align="center">inode位图区从4号块开始</td>
</tr>
<tr>
<td align="center">bg_inode_table</td>
<td align="center">0x05</td>
<td align="center">inode区从5号块开始</td>
</tr>
</tbody></table>
<h3 id="数据区位图和inode位图-bitmap"><a href="#数据区位图和inode位图-bitmap" class="headerlink" title="数据区位图和inode位图(bitmap)"></a>数据区位图和inode位图(bitmap)</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//以下为数据块位图区（3号块）</span></span><br><span class="line"><span class="number">00000</span>c00  ff ff ff ff ff ff <span class="number">01</span> <span class="number">00</span>  <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  |................|</span><br><span class="line"><span class="number">00000</span>c10  <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  |................|</span><br><span class="line">***</span><br><span class="line"><span class="comment">//以下为i节点位图区（4号块）</span></span><br><span class="line"><span class="number">00001000</span>  ff <span class="number">0f</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  |................|</span><br><span class="line"><span class="number">00001010</span>  <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  |................|</span><br><span class="line"><span class="number">00001020</span>  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|</span><br><span class="line">***</span><br></pre></td></tr></table></figure>

<h3 id="inode区"><a href="#inode区" class="headerlink" title="inode区"></a>inode区</h3><p>inode区从5号块开始，因此起始地址应该是0x400$\times{5}&#x3D;$0x1400，查看此处数据。另外根目录的inode是定死的，位于inode区的第2个，地址就是0x1400+128$\times$2&#x3D;0x1480（inode区的第一个inode没有意义）：</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//以下为inode区（5号块）</span></span><br><span class="line"><span class="number">00001400</span>  <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  |................|</span><br><span class="line">***</span><br><span class="line"><span class="comment">//以下为2号i节点（i节点从1开始编号），即根目录的i节点</span></span><br><span class="line"><span class="number">00001480</span>  ed <span class="number">41</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">04</span> <span class="number">00</span> <span class="number">00</span>  <span class="number">49</span> <span class="number">4</span>d <span class="number">9</span>e <span class="number">5</span>e <span class="number">46</span> <span class="number">4</span>a <span class="number">9</span>e <span class="number">5</span>e  |.A......IM.^FJ.^|</span><br><span class="line">                      ^_________^</span><br><span class="line">                      <span class="built_in">i_size</span>(bytes)</span><br><span class="line"><span class="number">00001490</span>  <span class="number">46</span> <span class="number">4</span>a <span class="number">9</span>e <span class="number">5</span>e <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  <span class="number">00</span> <span class="number">00</span> <span class="number">03</span> <span class="number">00</span> <span class="number">02</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  |FJ.^............|</span><br><span class="line">                                               ^_________^</span><br><span class="line">                                                i_blocks</span><br><span class="line"><span class="number">000014</span>a0  <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">01</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  <span class="number">25</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  |........%.......|</span><br><span class="line">                                   ^_________^</span><br><span class="line">                                    i_block</span><br><span class="line"><span class="number">000014b</span>0  <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  |................|</span><br><span class="line">***</span><br></pre></td></tr></table></figure>

<table>
<thead>
<tr>
<th align="center">字段</th>
<th align="center">值</th>
<th align="center">意义</th>
</tr>
</thead>
<tbody><tr>
<td align="center">i_size</td>
<td align="center">0x0400</td>
<td align="center">文件大小0x400B&#x3D;1KB</td>
</tr>
<tr>
<td align="center">i_blocks</td>
<td align="center">0x0002</td>
<td align="center">文件数据块数为2</td>
</tr>
<tr>
<td align="center">i_block</td>
<td align="center">0x0025</td>
<td align="center">第一个数据块的块号为37，偏移是0x400$\times$37&#x3D;0x9400</td>
</tr>
</tbody></table>
<h3 id="根目录数据块"><a href="#根目录数据块" class="headerlink" title="根目录数据块"></a>根目录数据块</h3><p>在地址0x9400处查看根目录数据块中的内容，其中记录着目录项：</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//以下为根目录的第一个数据块</span></span><br><span class="line"><span class="number">00009400</span>  <span class="number">02</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">0</span>c <span class="number">00</span> <span class="number">01</span> <span class="number">02</span>  <span class="number">2</span>e <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">02</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  |................|</span><br><span class="line">          ^_________^ ^___^ ^^ ^^  ^_________^ ^_________^</span><br><span class="line">          inode       rec_len      name         inode</span><br><span class="line">                            ^name_len </span><br><span class="line">                               ^file_type      ^第<span class="number">2</span>个目录项</span><br><span class="line"><span class="number">00009410</span>  <span class="number">0</span>c <span class="number">00</span> <span class="number">02</span> <span class="number">02</span> <span class="number">2</span>e <span class="number">2</span>e <span class="number">00</span> <span class="number">00</span>  <span class="number">0b</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">14</span> <span class="number">00</span> <span class="number">0</span>a <span class="number">02</span>  |................|</span><br><span class="line">          ^___^ ^^ ^^ ^_________^  ^_________^ ^___^ ^^ ^^</span><br><span class="line">                                   ^第<span class="number">3</span>个目录项</span><br><span class="line"><span class="number">00009420</span>  <span class="number">6</span>c <span class="number">6f</span> <span class="number">73</span> <span class="number">74</span> <span class="number">2b</span> <span class="number">66</span> <span class="number">6f</span> <span class="number">75</span>  <span class="number">6</span>e <span class="number">64</span> <span class="number">00</span> <span class="number">00</span> <span class="number">0</span>c <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  |lost+found......|</span><br><span class="line">          ^__________________________________^ ^_________^</span><br><span class="line">          ^文件名lost+found，末尾用\<span class="number">0</span>补充        ^第<span class="number">4</span>个目录项</span><br><span class="line"><span class="number">00009430</span>  d4 <span class="number">03</span> <span class="number">09</span> <span class="number">01</span> <span class="number">68</span> <span class="number">65</span> <span class="number">6</span>c <span class="number">6</span>c  <span class="number">6f</span> <span class="number">2</span>e <span class="number">74</span> <span class="number">78</span> <span class="number">74</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  |....hello.txt...|</span><br><span class="line">          ^___^ ^^ ^^ ^__________________________________^</span><br><span class="line">                      ^名字hello.txt</span><br><span class="line"><span class="number">00009440</span>  <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  |................|</span><br></pre></td></tr></table></figure>

<table>
<thead>
<tr>
<th align="center">inode号</th>
<th align="center">目录项长度</th>
<th align="center">文件名长度</th>
<th align="center">文件类型</th>
<th align="center">文件名</th>
</tr>
</thead>
<tbody><tr>
<td align="center">0x02</td>
<td align="center">0x0c: 12 Bytes</td>
<td align="center">0x1</td>
<td align="center">目录</td>
<td align="center">.</td>
</tr>
<tr>
<td align="center">0x02</td>
<td align="center">0x0c: 12 Bytes</td>
<td align="center">0x1</td>
<td align="center">目录</td>
<td align="center">..</td>
</tr>
<tr>
<td align="center">0x0b</td>
<td align="center">0x14: 20 Bytes</td>
<td align="center">0x0a: 10</td>
<td align="center">目录</td>
<td align="center">lost+found</td>
</tr>
<tr>
<td align="center">0x0c</td>
<td align="center">0x3d4 Bytes</td>
<td align="center">0x09</td>
<td align="center">普通文件</td>
<td align="center">hello.txt</td>
</tr>
</tbody></table>
<p>这是根目录下的目录项，注意到第1个和第2个目录项的inode号都是0x02号inode，指向根目录自己（打开当前目录和打开上一级目录都是指向自己）。此外hello.txt的inode号为0x0c，因此hello.txt的inode的地址为0x1400+0x80$\times$(0x0c-1)&#x3D;0x1980，在此处查看hello.txt的inode信息。</p>
<h3 id="hello-txt的inode"><a href="#hello-txt的inode" class="headerlink" title="hello.txt的inode"></a>hello.txt的inode</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//以下为hello.txt的i节点（12号）</span></span><br><span class="line"><span class="number">00001980</span>  a4 <span class="number">81</span> <span class="number">00</span> <span class="number">00</span> <span class="number">0</span>e <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  <span class="number">56</span> <span class="number">4</span>a <span class="number">9</span>e <span class="number">5</span>e <span class="number">46</span> <span class="number">4</span>a <span class="number">9</span>e <span class="number">5</span>e  |........VJ.^FJ.^|</span><br><span class="line"><span class="number">00001990</span>  <span class="number">46</span> <span class="number">4</span>a <span class="number">9</span>e <span class="number">5</span>e <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  <span class="number">00</span> <span class="number">00</span> <span class="number">01</span> <span class="number">00</span> <span class="number">02</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  |FJ.^............|</span><br><span class="line"><span class="number">000019</span>a0  <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">01</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  <span class="number">01</span> <span class="number">02</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  |................|</span><br><span class="line">                                   ^_________^</span><br><span class="line">                                     i_block:第一个数据块号</span><br><span class="line"><span class="number">000019b</span>0  <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  |................|</span><br><span class="line">***</span><br></pre></td></tr></table></figure>
<p>hello.txt的inode信息说明第一个数据块的块号为0x0201，对应偏移是0x400$\times$0x201&#x3D;0x80400，查看该地址处的数据块的内容。</p>
<h3 id="hello-txt的数据块"><a href="#hello-txt的数据块" class="headerlink" title="hello.txt的数据块"></a>hello.txt的数据块</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//以下为hello.txt的第一个数据块</span></span><br><span class="line"><span class="number">00080400</span>  <span class="number">48</span> <span class="number">65</span> <span class="number">6</span>c <span class="number">6</span>c <span class="number">6f</span> <span class="number">2</span>c <span class="number">20</span> <span class="number">77</span>  <span class="number">6f</span> <span class="number">72</span> <span class="number">6</span>c <span class="number">64</span> <span class="number">21</span> <span class="number">0</span>a <span class="number">00</span> <span class="number">00</span>  |Hello, world!...|</span><br><span class="line"><span class="number">00080410</span>  <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  |................|</span><br><span class="line">***</span><br></pre></td></tr></table></figure>
<p>数据块中存储着hello.txt的ASCII码。</p>
<h3 id="lost-found的inode"><a href="#lost-found的inode" class="headerlink" title="lost+found的inode"></a>lost+found的inode</h3><p>根目录中lost+found目录的inode编号为0x0b，因此lost+found目录文件的inode地址为0x1400+0x80$\times$(0x0b-1)&#x3D;0x1900，在此处查看lost+found的inode信息。</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//以下为lost+found的inode</span></span><br><span class="line"><span class="number">00001900</span>  ed <span class="number">41</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">30</span> <span class="number">00</span> <span class="number">00</span>  d7 <span class="number">49</span> <span class="number">9</span>e <span class="number">5</span>e d7 <span class="number">49</span> <span class="number">9</span>e <span class="number">5</span>e  |.A..<span class="number">.0</span>...I.^.I.^|</span><br><span class="line"><span class="number">00001910</span>  d7 <span class="number">49</span> <span class="number">9</span>e <span class="number">5</span>e <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  <span class="number">00</span> <span class="number">00</span> <span class="number">02</span> <span class="number">00</span> <span class="number">18</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  |.I.^............|</span><br><span class="line"><span class="number">00001920</span>  <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  <span class="number">26</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">27</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  |........&amp;..<span class="number">.&#x27;</span>...|</span><br><span class="line">                                   ^_________^ ^_________^</span><br><span class="line">                                     i_block     i_block</span><br><span class="line">                                 第一个数据块标号  第二个数据块标号</span><br><span class="line"><span class="number">00001930</span>  <span class="number">28</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">29</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  <span class="number">2</span>a <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">2b</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  |(...)...*...+...|</span><br><span class="line"><span class="number">00001940</span>  <span class="number">2</span>c <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">2</span>d <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  <span class="number">2</span>e <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">2f</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  |,...-......./...|</span><br><span class="line"><span class="number">00001950</span>  <span class="number">30</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">31</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  |<span class="number">0.</span>.<span class="number">.1</span>...........|</span><br><span class="line"><span class="number">00001960</span>  <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  |................|</span><br><span class="line">***</span><br></pre></td></tr></table></figure>
<p>lost+found第一个数据块的块号为0x0026，对应偏移是0x400$\times$0x26&#x3D;0x9800，查看该地址处的数据块的内容。</p>
<h3 id="lost-found数据块内容"><a href="#lost-found数据块内容" class="headerlink" title="lost+found数据块内容"></a>lost+found数据块内容</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//以下为lost+found的目录项数据块</span></span><br><span class="line"><span class="number">00009800</span>  <span class="number">0b</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">0</span>c <span class="number">00</span> <span class="number">01</span> <span class="number">02</span>  <span class="number">2</span>e <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">02</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  |................|</span><br><span class="line">          ^_________^ ^___^ ^^ ^^  ^_________^ ^_________^</span><br><span class="line">          inode       rec_len      name         inode</span><br><span class="line">                            ^name_len </span><br><span class="line">                               ^file_type      ^第<span class="number">2</span>个目录项</span><br><span class="line"><span class="number">00009810</span>  f4 <span class="number">03</span> <span class="number">02</span> <span class="number">02</span> <span class="number">2</span>e <span class="number">2</span>e <span class="number">00</span> <span class="number">00</span>  <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  |................|</span><br><span class="line">          ^___^ ^^ ^^ ^_________^</span><br><span class="line"><span class="number">00009820</span>  <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  |................|</span><br><span class="line">***</span><br><span class="line"><span class="number">00009</span>c00  <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">04</span> <span class="number">00</span> <span class="number">00</span>  <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  |................|</span><br><span class="line"><span class="number">00009</span>c10  <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  |................|</span><br><span class="line">***</span><br></pre></td></tr></table></figure>
<table>
<thead>
<tr>
<th align="center">inode号</th>
<th align="center">目录项长度</th>
<th align="center">文件名长度</th>
<th align="center">文件类型</th>
<th align="center">文件名</th>
</tr>
</thead>
<tbody><tr>
<td align="center">0x0b</td>
<td align="center">0x0c: 12 Bytes</td>
<td align="center">0x1</td>
<td align="center">目录</td>
<td align="center">.</td>
</tr>
<tr>
<td align="center">0x02</td>
<td align="center">0x03f4Bytes</td>
<td align="center">0x2</td>
<td align="center">目录</td>
<td align="center">..</td>
</tr>
<tr>
<td align="center">当前目录inode指向自己，而上一级目录指向根目录。</td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
</tbody></table>

      
    </div>
    <footer class="article-footer">
      <a data-url="https://chudod.gitee.io/myworks/2022/05/18/OS_FileSystem/" data-id="cl3kznr05000oj0ukhacvegql" data-title="文件系统概念和Ext2文件系统" class="article-share-link">Share</a>
      
      
      
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/myworks/tags/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/" rel="tag">操作系统</a></li></ul>

    </footer>
  </div>
  
</article>



  
    <article id="post-English_Sentences" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/myworks/2022/05/14/English_Sentences/" class="article-date">
  <time class="dt-published" datetime="2022-05-13T16:00:00.000Z" itemprop="datePublished">2022-05-14</time>
</a>
    
  <div class="article-category">
    <a class="article-category-link" href="/myworks/categories/English/">English</a>
  </div>

  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="p-name article-title" href="/myworks/2022/05/14/English_Sentences/">English Sentences</a>
    </h1>
  

      </header>
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h1 id="国家和社会"><a href="#国家和社会" class="headerlink" title="国家和社会"></a>国家和社会</h1><p>1、Thus, jointly making contributions to Chinese Great Rejuvenation.<br>   为实现中华民族的伟大复兴而奋斗。</p>
<p>2、Humanity is an inexorable upward march.<br>   人类进步的脚步不可阻挡。</p>
<h1 id="个人"><a href="#个人" class="headerlink" title="个人"></a>个人</h1><p>1、The conventional education focuses on convergent thinking rather than divergent thinking.<br>   传统的教育关注聚合思维，而不是发散性思维。</p>

      
    </div>
    <footer class="article-footer">
      <a data-url="https://chudod.gitee.io/myworks/2022/05/14/English_Sentences/" data-id="cl3kznqzu0004j0uk4gydgxcs" data-title="English Sentences" class="article-share-link">Share</a>
      
      
      
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/myworks/tags/English-Writing/" rel="tag">English Writing</a></li></ul>

    </footer>
  </div>
  
</article>



  
    <article id="post-English_Vocabulary" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/myworks/2022/05/11/English_Vocabulary/" class="article-date">
  <time class="dt-published" datetime="2022-05-10T16:00:00.000Z" itemprop="datePublished">2022-05-11</time>
</a>
    
  <div class="article-category">
    <a class="article-category-link" href="/myworks/categories/English/">English</a>
  </div>

  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="p-name article-title" href="/myworks/2022/05/11/English_Vocabulary/">English Vocabulary</a>
    </h1>
  

      </header>
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h1 id="词根词缀"><a href="#词根词缀" class="headerlink" title="词根词缀"></a>词根词缀</h1><h2 id="1、vent"><a href="#1、vent" class="headerlink" title="1、vent"></a>1、vent</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">graph TD</span><br><span class="line">A(vent: to come)--&gt;B1(advent 出现 到来)</span><br><span class="line">A--&gt;B2(venture 投机活动)</span><br><span class="line">B2--&gt;D1(joint venture 合资子公司)</span><br></pre></td></tr></table></figure>

<h1 id="分类"><a href="#分类" class="headerlink" title="分类"></a>分类</h1><h2 id="1、政治"><a href="#1、政治" class="headerlink" title="1、政治"></a>1、政治</h2><table>
<thead>
<tr>
<th align="center">单词</th>
<th align="center">释义</th>
<th align="center">单词</th>
<th align="center">释义</th>
<th align="center">单词</th>
<th align="center">释义</th>
<th align="center">单词</th>
<th align="center">释义</th>
</tr>
</thead>
<tbody><tr>
<td align="center">constitution</td>
<td align="center">宪法</td>
<td align="center">corruption</td>
<td align="center">腐败</td>
<td align="center">bribery</td>
<td align="center">贿赂</td>
<td align="center">ethic</td>
<td align="center">道德</td>
</tr>
<tr>
<td align="center">ethnic minorities</td>
<td align="center">少数民族</td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
</tbody></table>

      
    </div>
    <footer class="article-footer">
      <a data-url="https://chudod.gitee.io/myworks/2022/05/11/English_Vocabulary/" data-id="cl3kznqzv0005j0uk1amfah89" data-title="English Vocabulary" class="article-share-link">Share</a>
      
      
      
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/myworks/tags/English-Vocabulary/" rel="tag">English Vocabulary</a></li></ul>

    </footer>
  </div>
  
</article>



  
    <article id="post-Russian_Vocabulary" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/myworks/2022/05/11/Russian_Vocabulary/" class="article-date">
  <time class="dt-published" datetime="2022-05-10T16:00:00.000Z" itemprop="datePublished">2022-05-11</time>
</a>
    
  <div class="article-category">
    <a class="article-category-link" href="/myworks/categories/%D0%A0%D0%BE%D1%81%D1%81%D0%B8%D1%8F/">Россия</a>
  </div>

  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="p-name article-title" href="/myworks/2022/05/11/Russian_Vocabulary/">Русские Слова(俄语单词)</a>
    </h1>
  

      </header>
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h1 id="数字"><a href="#数字" class="headerlink" title="数字"></a>数字</h1><table>
<thead>
<tr>
<th align="center">单词</th>
<th align="center">释义</th>
<th align="center">单词</th>
<th align="center">释义</th>
<th align="center">单词</th>
<th align="center">释义</th>
<th align="center">单词</th>
<th align="center">释义</th>
</tr>
</thead>
<tbody><tr>
<td align="center">один</td>
<td align="center">一</td>
<td align="center">два</td>
<td align="center">二</td>
<td align="center">три</td>
<td align="center">三</td>
<td align="center">четыре</td>
<td align="center">四</td>
</tr>
<tr>
<td align="center">бять</td>
<td align="center">五</td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
</tbody></table>
<h1 id="国家"><a href="#国家" class="headerlink" title="国家"></a>国家</h1><table>
<thead>
<tr>
<th align="center">单词</th>
<th align="center">释义</th>
<th align="center">单词</th>
<th align="center">释义</th>
<th align="center">单词</th>
<th align="center">释义</th>
<th align="center">单词</th>
<th align="center">释义</th>
</tr>
</thead>
<tbody><tr>
<td align="center">Китай</td>
<td align="center">中国</td>
<td align="center">Совецкий Союз</td>
<td align="center">苏联</td>
<td align="center">Россия(России)</td>
<td align="center">俄罗斯</td>
<td align="center"></td>
<td align="center"></td>
</tr>
</tbody></table>
<h1 id="人称"><a href="#人称" class="headerlink" title="人称"></a>人称</h1>
      
    </div>
    <footer class="article-footer">
      <a data-url="https://chudod.gitee.io/myworks/2022/05/11/Russian_Vocabulary/" data-id="cl3kznr0a0012j0uk9hm8gz8j" data-title="Русские Слова(俄语单词)" class="article-share-link">Share</a>
      
      
      
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/myworks/tags/%D0%A0%D0%BE%D1%81%D1%81%D0%B8%D1%8F/" rel="tag">Россия</a></li></ul>

    </footer>
  </div>
  
</article>



  
    <article id="post-OS_ELF_execve" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/myworks/2022/05/06/OS_ELF_execve/" class="article-date">
  <time class="dt-published" datetime="2022-05-05T16:00:00.000Z" itemprop="datePublished">2022-05-06</time>
</a>
    
  <div class="article-category">
    <a class="article-category-link" href="/myworks/categories/%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/">计算机基础知识</a>►<a class="article-category-link" href="/myworks/categories/%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/">操作系统</a>
  </div>

  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="p-name article-title" href="/myworks/2022/05/06/OS_ELF_execve/">Linux程序执行与进程创建</a>
    </h1>
  

      </header>
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h1 id="一、程序的编译与执行"><a href="#一、程序的编译与执行" class="headerlink" title="一、程序的编译与执行"></a>一、程序的编译与执行</h1><h2 id="Program-Header"><a href="#Program-Header" class="headerlink" title="Program Header"></a>Program Header</h2><p>通常，我们写的代码都是编译、链接一气呵成，直接生成可执行文件，并且程序编译出来的虚拟起始地址通常是0x08048000，操作系统做了很多工作。例如将program.c编译和链接成可运行的文件:</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gcc program.c -o program</span><br></pre></td></tr></table></figure>
<p>这其中经过了编译和链接两个步骤：</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">gcc program.c -o program.o</span><br><span class="line">gcc program.o -o program</span><br></pre></td></tr></table></figure>
<p>得到的program.o只是一个待重定位文件，文件里面的符号（函数和变量）还没有安排地址，将来在链接的时候与其他文件“组合”成一个可执行文件时再重新定位（安排地址）。“组合”指的就是链接。因为在编译期间不知道会链接那些文件，所以干脆在链接的阶段一起编址，形成一个可重定位文件。<br>程序之间调用的最简单的方式是$\verb+call+$和$\verb+jmp+$，例如BIOS调用MBR以及MBR调用Loader，MBR的物理地址是0x7c00，而Loader的地址可以是0x900，通常事先约定好调用地址。这种方法非常不灵活，因此一种灵活的方法便是程序的入口地址信息与程序绑定，在程序文件中专门腾出一个空间来写程序的入口地址、程序的大小等等信息。原先的可执行二进制文件(program body)加上新的文件头(program header)，就形成了一种新的文件格式这种具有程序头文件格式的程序文件从外存读入内存中后，从该程序文件的头读出程序入口地址，跨过程序头，跳转到入口地址执行。</p>
<h2 id="ELF文件格式"><a href="#ELF文件格式" class="headerlink" title="ELF文件格式"></a>ELF文件格式</h2><h3 id="ELF文件格式整体视图"><a href="#ELF文件格式整体视图" class="headerlink" title="ELF文件格式整体视图"></a>ELF文件格式整体视图</h3><p>Windows系统下的可执行文件格式是PE（Portable Executable，exe是文件拓展名，不是真正的格式），而Linux的可执行文件格式是ELF(Executable and Linkable Format，可执行连接格式)。ELF文件是经过编译和链接之后，可以直接运行的二进制可执行文件。Linux中的.o文件和可执行二进制文件都是ELF格式的文件。ELF文件格式可以在&#x2F;usr&#x2F;include&#x2F;elf.h中可以找到ELF文件格式的所有定义。<br>程序最重要的概念是段(segment)和节(section)，其中section是程序员在进行汇编程序设计时显示划分出的数据区、代码区、栈区等等，而不同程序在链接时，链接器将多个目标文件相同属性的section链接成一个segment，形成了可执行内存空间中的数据段、代码段等等。因此ELF格式重要有相应的数据结构来描述程序中不同的section和segment，一个段头(Program header，也叫程序头)用来描述一个段，一个节头(Section header)用来描述一个section，也就有了程序头表(Program header table，也可以称之为段头表)和节头表(Section header table)，本质就是用来分别存储段头和节头的两个数组。而程序头表和节头表的条目个数和表长也是不确定的，因此还需要另一个结构来描述程序头表和节头表，也就是ELF头(ELF Header)，因此整个ELF文件格式看起来如下图所示（图片来源：《操作系统真相还原》）。ELF文件格式真正的作用在链接和运行阶段，因此ELF文件格式布局也从这两方面展示。</p>
<head>
    <meta charset="utf-8">
<style>
    .body{width:350px;height:200px}
</style>
<h4 align="center">ELF文件格式视图</h4>
<table align="center" border="1" width="700px" cellspacing="7">
<tr>
    <td style="border: 1px solid black" align="center">链接视图</td>
    <td style="border: 1px solid black" align="center">运行视图</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">ELF Header(elf头)</td>
    <td style="border: 1px solid black" align="center">ELF Header(elf头)</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">Program Header Table(程序头表，非必须，可选)</td>
    <td style="border: 1px solid black" align="center">Program Header Table(程序头表)</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">Section 1(节 1)</td>
    <td style="border: 1px solid black" rowspan="2" align="center">Segment 1(段1)</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">...</th>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">...</th>
    <td style="border: 1px solid black" rowspan="2" align="center">Segment 2(段2)</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">Section n(节 n)</th>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">...</th>
    <td style="border: 1px solid black" align="center">...</th>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">Section Header Table(程序头表)</td>
    <td style="border: 1px solid black" align="center">Section Header Table(程序头表，非必须，可选)</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">...</th>
    <td style="border: 1px solid black" align="center">...</th>
</tr>
<tr>
    <td class="body" style="border: 1px solid black" align="center">带重定位文件体(Program Body)</td>
    <td class="body" style="border: 1px solid black" align="center">可执行文件体(Program Body)</td>
</tr>
</table>

<h3 id="ELF-Header数据结构"><a href="#ELF-Header数据结构" class="headerlink" title="ELF Header数据结构"></a>ELF Header数据结构</h3><p>ELF Header结构定义在&#x2F;usr&#x2F;include&#x2F;elf.h中的$\verb+struct Elf32_Ehdr+$中，结构体定义如下所示：</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">typedef</span> <span class="keyword">struct</span></span><br><span class="line">&#123;</span><br><span class="line">  <span class="type">unsigned</span> <span class="type">char</span>	e_ident[EI_NIDENT];	    <span class="comment">/* Magic number and other info */</span></span><br><span class="line">  Elf32_Half	e_type;			        <span class="comment">/* Object file type */</span></span><br><span class="line">  Elf32_Half	e_machine;		        <span class="comment">/* Architecture */</span></span><br><span class="line">  Elf32_Word	e_version;		        <span class="comment">/* Object file version */</span></span><br><span class="line">  Elf32_Addr    e_entry;		        <span class="comment">/* Entry point virtual address */</span></span><br><span class="line">  Elf32_Off     e_phoff;		        <span class="comment">/* Program header table file offset */</span></span><br><span class="line">  Elf32_Off     e_shoff;		        <span class="comment">/* Section header table file offset */</span></span><br><span class="line">  Elf32_Word	e_flags;		        <span class="comment">/* Processor-specific flags */</span></span><br><span class="line">  Elf32_Half	e_ehsize;		        <span class="comment">/* ELF header size in bytes */</span></span><br><span class="line">  Elf32_Half	e_phentsize;		    <span class="comment">/* Program header table entry size */</span></span><br><span class="line">  Elf32_Half	e_phnum;		        <span class="comment">/* Program header table entry count */</span></span><br><span class="line">  Elf32_Half	e_shentsize;		    <span class="comment">/* Section header table entry size */</span></span><br><span class="line">  Elf32_Half	e_shnum;		        <span class="comment">/* Section header table entry count */</span></span><br><span class="line">  Elf32_Half	e_shstrndx;		        <span class="comment">/* Section header string table index */</span></span><br><span class="line">&#125; Elf32_Ehdr;</span><br></pre></td></tr></table></figure>
<p>其中e_ident[16]是16字节大小的数组，用来表示魔数以及其他的信息，具体含义如下表所示。</p>
<head>
    <meta charset="utf-8">
<style>
    .leftbody{width:300px;height:100px}
    .rightbody{width:400px;height:100px}
</style>
<h4 align="center">e_ident[16]数组</h4>
<table align="center" border="1" width="700px" cellspacing="7">
<tr>
    <td style="border: 1px solid black" align="center">e_ident[]成员</td>
    <td style="border: 1px solid black" align="center">意义</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">e_ident[0] = 0x7f</td>
    <td style="border: 1px solid black" rowspan="4" align="center">这4位是ELF文件的魔数(magic number)，表明这是一个ELF文件，e_ident[1]~e_ident[3]这3个变量表示‘E’、‘L’、‘F’这三个字符</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">e_ident[1] = 'E'</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">e_ident[2] = 'L'</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">e_ident[3] = 'F'</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">e_ident[4]</td>
    <td style="border: 1px solid black" align="center">ELF文件类型，值为0表示不可识别，值为1表示32位elf文件，值2表示64位elf文件</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">e_ident[5]</td>
    <td style="border: 1px solid black" align="center">编码格式，值为0：非法编码，值为1：小端字节序LSB，值为2：大端字节序MSB</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">e_ident[6]</td>
    <td style="border: 1px solid black" align="center">版本信息，默认为1</td>
</tr>
<tr>
    <td class="leftbody" style="border: 1px solid black" align="center">e_ident[7～15]</td>
    <td class="rightbody" style="border: 1px solid black" align="center">保留位，初始化为0</td>
</tr>
</table>

<p>而$\verb+struct Elf32_Ehdr+$中的所有成员的定义如下：</p>
<head>
    <meta charset="utf-8">
<style>
    .leftbody{width:200px;height:30px}
    .rightbody{width:500px;height:30px}
</style>
<h4 align="center">struct Elf32_Ehdr成员定义</h4>
<table align="center" border="1" width="700px" cellspacing="7">
<tr>
    <td style="border: 1px solid black" align="center">e_ident[16]</td>
    <td style="border: 1px solid black" align="center">魔数和其他信息</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">e_type</td>
    <td style="border: 1px solid black" align="center">2字节，目标文件类型，值0：位置格式文件，值1：可重定位文件，值2：可执行文件，值3：动态共享目标文件，值4：core文件（程序崩溃时内存映像转储格式），其他值无需关注</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">e_machine</td>
    <td style="border: 1px solid black" align="center">2字节，elf文件所属体系结构，值2：SPARC，值3：Intel 80386，值7：Intel 80860，值8：MPIS RS3000等等</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">e_version</td>
    <td style="border: 1px solid black" align="center">4字节，版本信息</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">e_entry</td>
    <td style="border: 1px solid black" align="center">4字节，操作系统运行该程序时，将控制权转交到的虚拟地址</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">e_phoff</td>
    <td style="border: 1px solid black" align="center">4字节，程序头表(program header table)在文件内的字节偏移量，若没有程序头表，则该值为0</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">e_shoff</td>
    <td style="border: 1px solid black" align="center">4字节，节头表(section header table)在文件内的字节偏移量，若没有节头表，则该值为0</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">e_flags</td>
    <td style="border: 1px solid black" align="center">4字节，处理器相关的标志</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">e_ehsize</td>
    <td style="border: 1px solid black" align="center">2字节，elf header的字节大小</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">e_phentsize</td>
    <td style="border: 1px solid black" align="center">2字节，程序头表(program header table)的每个条目(entry)的字节大小，该条目就是后面将要引出的struct Elf32_Phdr</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">e_phnum</td>
    <td style="border: 1px solid black" align="center">2字节，程序头表(program header table)的条目(entry)个数，即程序中有多少个段</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">e_shentsize</td>
    <td style="border: 1px solid black" align="center">2字节，节头表(section header table)的每个条目的字节大小</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">e_shnum</td>
    <td style="border: 1px solid black" align="center">2字节，节头表(section header table)的条目个数</td>
</tr>
<tr>
    <td class="leftbody" style="border: 1px solid black" align="center">e_shstrndx</td>
    <td class="leftbody" style="border: 1px solid black" align="center">2字节，Section header string table在节头表中的索引</td>
</tr>
</table>

<p>接下来是程序头表中条目的数据结构，也就是用来描述各个段(segment)的信息，其结构体为$\verb+struct Elf32_Phdr+$，如下所示：</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* Program segment header.  */</span></span><br><span class="line"><span class="keyword">typedef</span> <span class="keyword">struct</span></span><br><span class="line">&#123;</span><br><span class="line">  Elf32_Word	p_type;			<span class="comment">/* Segment type */</span></span><br><span class="line">  Elf32_Off	    p_offset;		<span class="comment">/* Segment file offset */</span></span><br><span class="line">  Elf32_Addr	p_vaddr;		<span class="comment">/* Segment virtual address */</span></span><br><span class="line">  Elf32_Addr	p_paddr;		<span class="comment">/* Segment physical address */</span></span><br><span class="line">  Elf32_Word	p_filesz;		<span class="comment">/* Segment size in file */</span></span><br><span class="line">  Elf32_Word	p_memsz;		<span class="comment">/* Segment size in memory */</span></span><br><span class="line">  Elf32_Word	p_flags;		<span class="comment">/* Segment flags */</span></span><br><span class="line">  Elf32_Word	p_align;		<span class="comment">/* Segment alignment */</span></span><br><span class="line">&#125; Elf32_Phdr;</span><br></pre></td></tr></table></figure>
<p>结构体中的各个成员的信息如下表所示：</p>
<head>
    <meta charset="utf-8">
<style>
    .leftbody{width:200px;height:30px}
    .rightbody{width:500px;height:30px}
</style>
<h4 align="center">struct Elf32_Phdr成员定义</h4>
<table align="center" border="1" width="700px" cellspacing="7">
<tr>
    <td style="border: 1px solid black" align="center">p_type</td>
    <td style="border: 1px solid black" align="center">4字节，表示程序中该段的类型，值1：可加载程序段，值2：动态链接信息，值3：动态加载器名称，值6：程序头表，以及其他无需关注的信息</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">p_offset</td>
    <td style="border: 1px solid black" align="center">4字节，本段在文件内的起始偏移地址</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">p_vaddr</td>
    <td style="border: 1px solid black" align="center">4字节，本段在内存中的起始虚拟地址</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">p_paddr</td>
    <td style="border: 1px solid black" align="center">4字节，仅用于与物理地址相关的系统如System V中</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">p_filesz</td>
    <td style="border: 1px solid black" align="center">4字节，本段在文件中的大小</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">p_memsz</td>
    <td style="border: 1px solid black" align="center">4字节，本段在内存中的大小</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">p_flags</td>
    <td style="border: 1px solid black" align="center">4字节，本段相关的标志，0b1：可执行，0b10：可写，0b100：可读，以及其他标志</td>
</tr>
<tr>
    <td class="leftbody" style="border: 1px solid black" align="center">p_align</td>
    <td class="rightbody" style="border: 1px solid black" align="center">4字节，本段在内存和文件中的对齐方式，若值为0或值1，则不对齐，否则其为2的幂次</td>
</tr>
</table>

<h3 id="实验程序实例"><a href="#实验程序实例" class="headerlink" title="实验程序实例"></a>实验程序实例</h3><p>一共两个程序，分别为parent.c和child.c，其中在parent.c中父进程会$\verb+fork+$一个子进程，子进程会利用$\verb+execve+$系统调用来将child.c加载进自己的进程空间，执行这一段新的程序。<br>这个是父进程执行的程序：</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/*parent.c*/</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string">&lt;sys/types.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string">&lt;stdio.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string">&lt;string.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string">&lt;unistd.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="type">char</span> str1[<span class="number">4096</span>] = &#123;<span class="string">&quot;String of parent process.\n&quot;</span>&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="type">pid_t</span> pid;</span><br><span class="line">    pid = fork();</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span>(pid &lt; <span class="number">0</span>)             <span class="comment">/*Error occured*/</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="built_in">fprintf</span>(stderr, <span class="string">&quot;Fork failed!\n&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span>(pid == <span class="number">0</span>)            <span class="comment">/*Child process*/</span></span><br><span class="line">    &#123;</span><br><span class="line">	    <span class="built_in">printf</span>(<span class="string">&quot;%s&quot;</span>, str1);</span><br><span class="line">        <span class="built_in">strcpy</span>(str1, <span class="string">&quot;String of child process.\n&quot;</span>);</span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">&quot;%s&quot;</span>, str1);</span><br><span class="line">        <span class="built_in">execve</span>(<span class="string">&quot;./child&quot;</span>, <span class="literal">NULL</span>, <span class="literal">NULL</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">else</span>                    <span class="comment">/*Parent process*/</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="built_in">wait</span>(<span class="literal">NULL</span>);</span><br><span class="line">	    <span class="built_in">strcpy</span>(str1, <span class="string">&quot;Running in parent process.\n&quot;</span>);</span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">&quot;%s&quot;</span>, str1);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>这个是子进程加载的新程序：</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/*child.c*/</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string">&lt;sys/types.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string">&lt;stdio.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string">&lt;string.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string">&lt;unistd.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="type">char</span> str2[<span class="number">4096</span>] = &#123;<span class="string">&quot;Child process is runing another program!\n&quot;</span>&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="type">char</span>* ptr2 = (<span class="type">char</span>*)<span class="built_in">malloc</span>(<span class="built_in">sizeof</span>(<span class="type">char</span>) * (<span class="built_in">strlen</span>(str2) + <span class="number">1</span>));</span><br><span class="line">    <span class="built_in">memset</span>(ptr2, <span class="number">0</span>, <span class="built_in">sizeof</span>(ptr2));</span><br><span class="line">    <span class="built_in">strcpy</span>(ptr2, str2);</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">&quot;%s&quot;</span>, ptr2);</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="ELF-Header实例"><a href="#ELF-Header实例" class="headerlink" title="ELF Header实例"></a>ELF Header实例</h3><p>可以利用xxd命令来查看ELF文件格式信息，新建一个xxd.sh脚本，其内容为：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">xxd -g <span class="number">1</span> -s $<span class="number">2</span> -l $<span class="number">3</span> $<span class="number">1</span></span><br></pre></td></tr></table></figure>
<p>然后在命令行中输入</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sh ./xxd.sh ./child <span class="number">0</span> <span class="number">300</span></span><br></pre></td></tr></table></figure>
<p>即可查看child文件的ELF格式信息。上面参数的意思是查看0~300字节的ELF文件格式信息。在学校提供的实验平台上得到的结果如下所示：</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">00000000</span>: <span class="number">7f</span> <span class="number">45</span> <span class="number">4</span>c <span class="number">46</span> <span class="number">01</span> <span class="number">01</span> <span class="number">01</span> <span class="number">03</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  .ELF............</span><br><span class="line"><span class="number">00000010</span>: <span class="number">02</span> <span class="number">00</span> <span class="number">03</span> <span class="number">00</span> <span class="number">01</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">0</span>a <span class="number">8</span>d <span class="number">04</span> <span class="number">08</span> <span class="number">34</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  ...........<span class="number">.4</span>...</span><br><span class="line"><span class="number">00000020</span>: <span class="number">0</span>c <span class="number">34</span> <span class="number">0</span>a <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">34</span> <span class="number">00</span> <span class="number">20</span> <span class="number">00</span> <span class="number">06</span> <span class="number">00</span> <span class="number">28</span> <span class="number">00</span>  <span class="number">.4</span>.....<span class="number">.4</span>. ...(.</span><br><span class="line"><span class="number">00000030</span>: <span class="number">24</span> <span class="number">00</span> <span class="number">21</span> <span class="number">00</span> <span class="number">01</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">80</span> <span class="number">04</span> <span class="number">08</span>  $.!.............</span><br><span class="line"><span class="number">00000040</span>: <span class="number">00</span> <span class="number">80</span> <span class="number">04</span> <span class="number">08</span> <span class="number">6f</span> <span class="number">00</span> <span class="number">0</span>a <span class="number">00</span> <span class="number">6f</span> <span class="number">00</span> <span class="number">0</span>a <span class="number">00</span> <span class="number">05</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  ....o...o.......</span><br><span class="line"><span class="number">00000050</span>: <span class="number">00</span> <span class="number">10</span> <span class="number">00</span> <span class="number">00</span> <span class="number">01</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">58</span> <span class="number">0f</span> <span class="number">0</span>a <span class="number">00</span> <span class="number">58</span> <span class="number">9f</span> <span class="number">0</span>e <span class="number">08</span>  ........X...X...</span><br><span class="line"><span class="number">00000060</span>: <span class="number">58</span> <span class="number">9f</span> <span class="number">0</span>e <span class="number">08</span> <span class="number">48</span> <span class="number">20</span> <span class="number">00</span> <span class="number">00</span> cc <span class="number">33</span> <span class="number">00</span> <span class="number">00</span> <span class="number">06</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  X...H ..<span class="number">.3</span>......</span><br><span class="line"><span class="number">00000070</span>: <span class="number">00</span> <span class="number">10</span> <span class="number">00</span> <span class="number">00</span> <span class="number">04</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> f4 <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> f4 <span class="number">80</span> <span class="number">04</span> <span class="number">08</span>  ................</span><br><span class="line"><span class="number">00000080</span>: f4 <span class="number">80</span> <span class="number">04</span> <span class="number">08</span> <span class="number">44</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">44</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">04</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  ....D...D.......</span><br><span class="line"><span class="number">00000090</span>: <span class="number">04</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">07</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">58</span> <span class="number">0f</span> <span class="number">0</span>a <span class="number">00</span> <span class="number">58</span> <span class="number">9f</span> <span class="number">0</span>e <span class="number">08</span>  ........X...X...</span><br><span class="line"><span class="number">000000</span>a0: <span class="number">58</span> <span class="number">9f</span> <span class="number">0</span>e <span class="number">08</span> <span class="number">10</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">28</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">04</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  X.......(.......</span><br><span class="line"><span class="number">000000b</span>0: <span class="number">04</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">51</span> e5 <span class="number">74</span> <span class="number">64</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  ....Q.td........</span><br><span class="line"><span class="number">000000</span>c0: <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">06</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  ................</span><br><span class="line"><span class="number">000000</span>d0: <span class="number">10</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">52</span> e5 <span class="number">74</span> <span class="number">64</span> <span class="number">58</span> <span class="number">0f</span> <span class="number">0</span>a <span class="number">00</span> <span class="number">58</span> <span class="number">9f</span> <span class="number">0</span>e <span class="number">08</span>  ....R.tdX...X...</span><br><span class="line"><span class="number">000000e0</span>: <span class="number">58</span> <span class="number">9f</span> <span class="number">0</span>e <span class="number">08</span> a8 <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> a8 <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">04</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  X...............</span><br><span class="line"><span class="number">000000f</span>0: <span class="number">01</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">04</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">10</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">01</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  ................</span><br><span class="line"><span class="number">00000100</span>: <span class="number">47</span> <span class="number">4</span>e <span class="number">55</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">02</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">06</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  GNU.............</span><br><span class="line"><span class="number">00000110</span>: <span class="number">18</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">04</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">14</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">03</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span>  ................</span><br><span class="line"><span class="number">00000120</span>: <span class="number">47</span> <span class="number">4</span>e <span class="number">55</span> <span class="number">00</span> d9 <span class="number">5</span>e <span class="number">23</span> cf b2 <span class="number">2</span>c <span class="number">61</span> f1              GNU..^#..,a.</span><br></pre></td></tr></table></figure>
<p>因此child文件的ELF格式信息具体含义如下，其中0x00到0x33号内存单元是ELF Header(即$\verb+struct Elf+$)的内容，0x34到0xf4为program header(即$\verb+struct Elf32_Phdr+$)的内容，首先分析ELF Header信息：</p>
<head>
    <meta charset="utf-8">
<style>
    .leftbody{width:150px;height:30px}
    .midbody{width:150;height:300}
    .rightbody{width:400px;height:30px}
</style>
<h4 align="center">child文件的ELF Header信息</h4>
<table align="center" border="1" width="700px" cellspacing="7">
<tr>
    <td style="border: 1px solid black" align="center">成员</td>
    <td style="border: 1px solid black" align="center">值</td>
    <td style="border: 1px solid black" align="center">含义</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">e_ident[4]</td>
    <td style="border: 1px solid black" align="center">0x01</td>
    <td style="border: 1px solid black" align="center">32位的elf文件</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">e_ident[5]</td>
    <td style="border: 1px solid black" align="center">0x01</td>
    <td style="border: 1px solid black" align="center">小端字节序</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">e_type</td>
    <td style="border: 1px solid black" align="center">0x0002</td>
    <td style="border: 1px solid black" align="center">可执行文件</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">e_machine</td>
    <td style="border: 1px solid black" align="center">0x0003</td>
    <td style="border: 1px solid black" align="center">intel 80386平台</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">e_entry</td>
    <td style="border: 1px solid black" align="center">0x08048d0a</td>
    <td style="border: 1px solid black" align="center">程序的虚拟入口地址为0x08048d0a</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">e_phoff</td>
    <td style="border: 1px solid black" align="center">0x00000034</td>
    <td style="border: 1px solid black" align="center">程序头表在文件中的偏移量是0x34</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">e_shoff</td>
    <td style="border: 1px solid black" align="center">0x000a340c</td>
    <td style="border: 1px solid black" align="center">节头表在文件中的偏移量</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">e_ehsize</td>
    <td style="border: 1px solid black" align="center">0x0034</td>
    <td style="border: 1px solid black" align="center">elf header大小为0x34，可见程序头表后面跟着elf头</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">e_phentsize</td>
    <td style="border: 1px solid black" align="center">0x0020</td>
    <td style="border: 1px solid black" align="center">程序头表program header每个条目(struct Elf32_Phdr)的大小为0x20</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">e_phnum</td>
    <td style="border: 1px solid black" align="center">0x0006</td>
    <td style="border: 1px solid black" align="center">程序头表中的元素个数为6，即有6个段</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">e_shentsize</td>
    <td style="border: 1px solid black" align="center">0x0028</td>
    <td style="border: 1px solid black" align="center">节头表中各个节的大小</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">e_shnum</td>
    <td style="border: 1px solid black" align="center">0x0024</td>
    <td style="border: 1px solid black" align="center">节头表中元素个数，说明一共0x24=36个节</td>
</tr>
<tr>
    <td class="leftbody" style="border: 1px solid black" align="center">e_shstrndx</td>
    <td class="midbody" style="border: 1px solid black" align="center">0x0021</td>
    <td class="rightbody" style="border: 1px solid black" align="center">string name table在节头表中的索引为0x21</td>
</tr>
</table>

<p>然后分析程序头表program header的内容(第4行的0x34开始)，刚才ELF Header中可以知道，程序一共有6个段，且每个段的条目的大小为0x20。</p>
<head>
    <meta charset="utf-8">
<style>
    .leftbody{width:150px;height:30px}
    .midbody{width:150;height:300}
    .rightbody{width:400px;height:30px}
</style>
<h4 align="center">child文件的Program Header信息</h4>
<table align="center" border="1" width="700px" cellspacing="7">
<tr>
    <td style="border: 1px solid black" align="center">成员</td>
    <td style="border: 1px solid black" align="center">值</td>
    <td style="border: 1px solid black" align="center">含义</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">p_type</td>
    <td style="border: 1px solid black" align="center">0x00000001</td>
    <td style="border: 1px solid black" align="center">该程序为可加载程序段</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">p_offset</td>
    <td style="border: 1px solid black" align="center">0x00000000</td>
    <td style="border: 1px solid black" align="center">本段在文件内的偏移量为0x00</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">p_vaddr</td>
    <td style="border: 1px solid black" align="center">0x08048000</td>
    <td style="border: 1px solid black" align="center">该段被加载到内存后的起始虚拟地址！Elf Header中的e_entry是整个程序的入口地址(0x08048d0a)，而整个程序的起始地址是0x08048000。</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">p_paddr</td>
    <td style="border: 1px solid black" align="center">0x08048000</td>
    <td style="border: 1px solid black" align="center">和p_vaddr相似，不用管这个</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">p_filesz</td>
    <td style="border: 1px solid black" align="center">0x000a006f</td>
    <td style="border: 1px solid black" align="center">本段在文件中的字节大小</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">p_memsz</td>
    <td style="border: 1px solid black" align="center">0x000a006f</td>
    <td style="border: 1px solid black" align="center">本段在内存中的字节大小，等于p_filesz</td>
</tr>
<tr>
    <td style="border: 1px solid black" align="center">p_flags</td>
    <td style="border: 1px solid black" align="center">0x00000005</td>
    <td style="border: 1px solid black" align="center">5=4+1，因此该段可读可执行，据此推测出该段应该是代码段。</td>
</tr>
<tr>
    <td class="leftbody" style="border: 1px solid black" align="center">p_align</td>
    <td class="midbody" style="border: 1px solid black" align="center">0x00001000</td>
    <td class="rightbody" style="border: 1px solid black" align="center">本段的对齐方式为32字节对齐</td>
</tr>
</table>

<p>接下来看数据段的信息，在gdb调试窗口中打印str2的地址，为0x80ea080，并且数据段线性区的地址范围为0x80e9000到0x80ec000。<br>除了利用xxd命令查看ELF文件格式外，还可以利用readelf命令来查看。简单的输入：</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">readelf -e child</span><br></pre></td></tr></table></figure>
<p>即可得到如下信息：</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br></pre></td><td class="code"><pre><span class="line">ELF Header:</span><br><span class="line">  Magic:   <span class="number">7f</span> <span class="number">45</span> <span class="number">4</span>c <span class="number">46</span> <span class="number">01</span> <span class="number">01</span> <span class="number">01</span> <span class="number">03</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">00</span></span><br><span class="line">  Class:                             ELF32</span><br><span class="line">  Data:                              <span class="number">2&#x27;</span>s complement, little endian</span><br><span class="line">  Version:                           <span class="number">1</span> (current)</span><br><span class="line">  OS/ABI:                            UNIX - GNU</span><br><span class="line">  ABI Version:                       <span class="number">0</span></span><br><span class="line">  Type:                              <span class="built_in">EXEC</span> (Executable file)</span><br><span class="line">  Machine:                           Intel <span class="number">80386</span></span><br><span class="line">  Version:                           <span class="number">0x1</span></span><br><span class="line">  Entry point address:               <span class="number">0x8048d0a</span></span><br><span class="line">  Start of program headers:          <span class="number">52</span> (bytes into file)</span><br><span class="line">  Start of section headers:          <span class="number">668684</span> (bytes into file)</span><br><span class="line">  Flags:                             <span class="number">0x0</span></span><br><span class="line">  Size of <span class="keyword">this</span> header:               <span class="number">52</span> (bytes)</span><br><span class="line">  Size of program headers:           <span class="number">32</span> (bytes)</span><br><span class="line">  Number of program headers:         <span class="number">6</span></span><br><span class="line">  Size of section headers:           <span class="number">40</span> (bytes)</span><br><span class="line">  Number of section headers:         <span class="number">36</span></span><br><span class="line">  Section header string table index: <span class="number">33</span></span><br><span class="line"></span><br><span class="line">Section Headers:</span><br><span class="line">  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al</span><br><span class="line">  [ <span class="number">0</span>]                   <span class="literal">NULL</span>            <span class="number">00000000</span> <span class="number">000000</span> <span class="number">000000</span> <span class="number">00</span>      <span class="number">0</span>   <span class="number">0</span>  <span class="number">0</span></span><br><span class="line">  [ <span class="number">1</span>] .note.ABI-tag     NOTE            <span class="number">080480f</span>4 <span class="number">0000f</span>4 <span class="number">000020</span> <span class="number">00</span>   A  <span class="number">0</span>   <span class="number">0</span>  <span class="number">4</span></span><br><span class="line">  [ <span class="number">2</span>] .note.gnu.build-i NOTE            <span class="number">08048114</span> <span class="number">000114</span> <span class="number">000024</span> <span class="number">00</span>   A  <span class="number">0</span>   <span class="number">0</span>  <span class="number">4</span></span><br><span class="line">  [ <span class="number">3</span>] .rel.plt          REL             <span class="number">08048138</span> <span class="number">000138</span> <span class="number">000070</span> <span class="number">08</span>   A  <span class="number">0</span>   <span class="number">5</span>  <span class="number">4</span></span><br><span class="line">  [ <span class="number">4</span>] .init             PROGBITS        <span class="number">080481</span>a8 <span class="number">0001</span>a8 <span class="number">000023</span> <span class="number">00</span>  AX  <span class="number">0</span>   <span class="number">0</span>  <span class="number">4</span></span><br><span class="line">  [ <span class="number">5</span>] .plt              PROGBITS        <span class="number">080481</span>d0 <span class="number">0001</span>d0 <span class="number">0000e0</span> <span class="number">00</span>  AX  <span class="number">0</span>   <span class="number">0</span> <span class="number">16</span></span><br><span class="line">  [ <span class="number">6</span>] .text             PROGBITS        <span class="number">080482b</span>0 <span class="number">0002b</span>0 <span class="number">075134</span> <span class="number">00</span>  AX  <span class="number">0</span>   <span class="number">0</span> <span class="number">16</span></span><br><span class="line">  [ <span class="number">7</span>] __libc_freeres_fn PROGBITS        <span class="number">080b</span>d3f0 <span class="number">0753f</span>0 <span class="number">000</span>ad6 <span class="number">00</span>  AX  <span class="number">0</span>   <span class="number">0</span> <span class="number">16</span></span><br><span class="line">  [ <span class="number">8</span>] __libc_thread_fre PROGBITS        <span class="number">080b</span>ded0 <span class="number">075</span>ed0 <span class="number">00006f</span> <span class="number">00</span>  AX  <span class="number">0</span>   <span class="number">0</span> <span class="number">16</span></span><br><span class="line">  [ <span class="number">9</span>] .fini             PROGBITS        <span class="number">080b</span>df40 <span class="number">075f</span>40 <span class="number">000014</span> <span class="number">00</span>  AX  <span class="number">0</span>   <span class="number">0</span>  <span class="number">4</span></span><br><span class="line">  [<span class="number">10</span>] .rodata           PROGBITS        <span class="number">080b</span>df60 <span class="number">075f</span>60 <span class="number">01b</span>f90 <span class="number">00</span>   A  <span class="number">0</span>   <span class="number">0</span> <span class="number">32</span></span><br><span class="line">  [<span class="number">11</span>] __libc_subfreeres PROGBITS        <span class="number">080</span>d9ef0 <span class="number">091</span>ef0 <span class="number">00002</span>c <span class="number">00</span>   A  <span class="number">0</span>   <span class="number">0</span>  <span class="number">4</span></span><br><span class="line">  [<span class="number">12</span>] __libc_atexit     PROGBITS        <span class="number">080</span>d9f1c <span class="number">091f</span>1c <span class="number">000004</span> <span class="number">00</span>   A  <span class="number">0</span>   <span class="number">0</span>  <span class="number">4</span></span><br><span class="line">  [<span class="number">13</span>] __libc_thread_sub PROGBITS        <span class="number">080</span>d9f20 <span class="number">091f</span>20 <span class="number">000004</span> <span class="number">00</span>   A  <span class="number">0</span>   <span class="number">0</span>  <span class="number">4</span></span><br><span class="line">  [<span class="number">14</span>] .eh_frame         PROGBITS        <span class="number">080</span>d9f24 <span class="number">091f</span>24 <span class="number">00e0</span>a8 <span class="number">00</span>   A  <span class="number">0</span>   <span class="number">0</span>  <span class="number">4</span></span><br><span class="line">  [<span class="number">15</span>] .gcc_except_table PROGBITS        <span class="number">080e7</span>fcc <span class="number">09f</span>fcc <span class="number">0000</span>a3 <span class="number">00</span>   A  <span class="number">0</span>   <span class="number">0</span>  <span class="number">1</span></span><br><span class="line">  [<span class="number">16</span>] .tdata            PROGBITS        <span class="number">080e9</span>f58 <span class="number">0</span>a0f58 <span class="number">000010</span> <span class="number">00</span> WAT  <span class="number">0</span>   <span class="number">0</span>  <span class="number">4</span></span><br><span class="line">  [<span class="number">17</span>] .tbss             NOBITS          <span class="number">080e9</span>f68 <span class="number">0</span>a0f68 <span class="number">000018</span> <span class="number">00</span> WAT  <span class="number">0</span>   <span class="number">0</span>  <span class="number">4</span></span><br><span class="line">  [<span class="number">18</span>] .init_array       INIT_ARRAY      <span class="number">080e9</span>f68 <span class="number">0</span>a0f68 <span class="number">000008</span> <span class="number">00</span>  WA  <span class="number">0</span>   <span class="number">0</span>  <span class="number">4</span></span><br><span class="line">  [<span class="number">19</span>] .fini_array       FINI_ARRAY      <span class="number">080e9</span>f70 <span class="number">0</span>a0f70 <span class="number">000008</span> <span class="number">00</span>  WA  <span class="number">0</span>   <span class="number">0</span>  <span class="number">4</span></span><br><span class="line">  [<span class="number">20</span>] .jcr              PROGBITS        <span class="number">080e9</span>f78 <span class="number">0</span>a0f78 <span class="number">000004</span> <span class="number">00</span>  WA  <span class="number">0</span>   <span class="number">0</span>  <span class="number">4</span></span><br><span class="line">  [<span class="number">21</span>] .data.rel.ro      PROGBITS        <span class="number">080e9</span>f80 <span class="number">0</span>a0f80 <span class="number">000070</span> <span class="number">00</span>  WA  <span class="number">0</span>   <span class="number">0</span> <span class="number">32</span></span><br><span class="line">  [<span class="number">22</span>] .got              PROGBITS        <span class="number">080e9</span>ff0 <span class="number">0</span>a0ff0 <span class="number">000008</span> <span class="number">04</span>  WA  <span class="number">0</span>   <span class="number">0</span>  <span class="number">4</span></span><br><span class="line">  [<span class="number">23</span>] .got.plt          PROGBITS        <span class="number">080</span>ea000 <span class="number">0</span>a1000 <span class="number">000044</span> <span class="number">04</span>  WA  <span class="number">0</span>   <span class="number">0</span>  <span class="number">4</span></span><br><span class="line">  [<span class="number">24</span>] .data             PROGBITS        <span class="number">080</span>ea060 <span class="number">0</span>a1060 <span class="number">001f</span>40 <span class="number">00</span>  WA  <span class="number">0</span>   <span class="number">0</span> <span class="number">32</span></span><br><span class="line">  [<span class="number">25</span>] .bss              NOBITS          <span class="number">080</span>ebfa0 <span class="number">0</span>a2fa0 <span class="number">00136</span>c <span class="number">00</span>  WA  <span class="number">0</span>   <span class="number">0</span> <span class="number">32</span></span><br><span class="line">  [<span class="number">26</span>] __libc_freeres_pt NOBITS          <span class="number">080</span>ed30c <span class="number">0</span>a2fa0 <span class="number">000018</span> <span class="number">00</span>  WA  <span class="number">0</span>   <span class="number">0</span>  <span class="number">4</span></span><br><span class="line">  [<span class="number">27</span>] .comment          PROGBITS        <span class="number">00000000</span> <span class="number">0</span>a2fa0 <span class="number">00002b</span> <span class="number">01</span>  MS  <span class="number">0</span>   <span class="number">0</span>  <span class="number">1</span></span><br><span class="line">  [<span class="number">28</span>] .debug_aranges    PROGBITS        <span class="number">00000000</span> <span class="number">0</span>a2fcb <span class="number">000020</span> <span class="number">00</span>      <span class="number">0</span>   <span class="number">0</span>  <span class="number">1</span></span><br><span class="line">  [<span class="number">29</span>] .debug_info       PROGBITS        <span class="number">00000000</span> <span class="number">0</span>a2feb <span class="number">0000</span>dd <span class="number">00</span>      <span class="number">0</span>   <span class="number">0</span>  <span class="number">1</span></span><br><span class="line">  [<span class="number">30</span>] .debug_abbrev     PROGBITS        <span class="number">00000000</span> <span class="number">0</span>a30c8 <span class="number">0000</span>a0 <span class="number">00</span>      <span class="number">0</span>   <span class="number">0</span>  <span class="number">1</span></span><br><span class="line">  [<span class="number">31</span>] .debug_line       PROGBITS        <span class="number">00000000</span> <span class="number">0</span>a3168 <span class="number">00004</span>d <span class="number">00</span>      <span class="number">0</span>   <span class="number">0</span>  <span class="number">1</span></span><br><span class="line">  [<span class="number">32</span>] .debug_str        PROGBITS        <span class="number">00000000</span> <span class="number">0</span>a31b5 <span class="number">0000</span>cb <span class="number">01</span>  MS  <span class="number">0</span>   <span class="number">0</span>  <span class="number">1</span></span><br><span class="line">  [<span class="number">33</span>] .shstrtab         STRTAB          <span class="number">00000000</span> <span class="number">0</span>a3280 <span class="number">00018</span>c <span class="number">00</span>      <span class="number">0</span>   <span class="number">0</span>  <span class="number">1</span></span><br><span class="line">  [<span class="number">34</span>] .symtab           SYMTAB          <span class="number">00000000</span> <span class="number">0</span>a39ac <span class="number">008</span>c00 <span class="number">10</span>     <span class="number">35</span> <span class="number">1060</span>  <span class="number">4</span></span><br><span class="line">  [<span class="number">35</span>] .strtab           STRTAB          <span class="number">00000000</span> <span class="number">0</span>ac5ac <span class="number">007</span>ebd <span class="number">00</span>      <span class="number">0</span>   <span class="number">0</span>  <span class="number">1</span></span><br><span class="line">Key to Flags:</span><br><span class="line">  <span class="built_in">W</span> (write), <span class="built_in">A</span> (alloc), <span class="built_in">X</span> (execute), <span class="built_in">M</span> (merge), <span class="built_in">S</span> (strings)</span><br><span class="line">  <span class="built_in">I</span> (info), <span class="built_in">L</span> (link order), <span class="built_in">G</span> (group), <span class="built_in">T</span> (TLS), <span class="built_in">E</span> (exclude), <span class="built_in">x</span> (unknown)</span><br><span class="line">  <span class="built_in">O</span> (extra OS processing required) <span class="built_in">o</span> (OS specific), <span class="built_in">p</span> (processor specific)</span><br><span class="line"></span><br><span class="line">Program Headers:</span><br><span class="line">  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align</span><br><span class="line">  LOAD           <span class="number">0x000000</span> <span class="number">0x08048000</span> <span class="number">0x08048000</span> <span class="number">0xa006f</span> <span class="number">0xa006f</span> R E <span class="number">0x1000</span></span><br><span class="line">  LOAD           <span class="number">0x0a0f58</span> <span class="number">0x080e9f58</span> <span class="number">0x080e9f58</span> <span class="number">0x02048</span> <span class="number">0x033cc</span> RW  <span class="number">0x1000</span></span><br><span class="line">  NOTE           <span class="number">0x0000f4</span> <span class="number">0x080480f4</span> <span class="number">0x080480f4</span> <span class="number">0x00044</span> <span class="number">0x00044</span> R   <span class="number">0x4</span></span><br><span class="line">  TLS            <span class="number">0x0a0f58</span> <span class="number">0x080e9f58</span> <span class="number">0x080e9f58</span> <span class="number">0x00010</span> <span class="number">0x00028</span> R   <span class="number">0x4</span></span><br><span class="line">  GNU_STACK      <span class="number">0x000000</span> <span class="number">0x00000000</span> <span class="number">0x00000000</span> <span class="number">0x00000</span> <span class="number">0x00000</span> RW  <span class="number">0x10</span></span><br><span class="line">  GNU_RELRO      <span class="number">0x0a0f58</span> <span class="number">0x080e9f58</span> <span class="number">0x080e9f58</span> <span class="number">0x000a8</span> <span class="number">0x000a8</span> R   <span class="number">0x1</span></span><br><span class="line"></span><br><span class="line"> Section to Segment mapping:</span><br><span class="line">  Segment Sections...</span><br><span class="line">   <span class="number">00</span>     .note.ABI-tag .note.gnu.build-id .rel.plt .init .plt .text __libc_freeres_fn __libc_thread_freeres_fn .fini .rodata __libc_subfreeres __libc_atexit __libc_thread_subfreeres .eh_frame .gcc_except_table</span><br><span class="line">   <span class="number">01</span>     .tdata .init_array .fini_array .jcr .data.rel.ro .got .got.plt .data .bss __libc_freeres_ptrs</span><br><span class="line">   <span class="number">02</span>     .note.ABI-tag .note.gnu.build-id</span><br><span class="line">   <span class="number">03</span>     .tdata .tbss</span><br><span class="line">   <span class="number">04</span></span><br><span class="line">   <span class="number">05</span>     .tdata .init_array .fini_array .jcr .data.rel.ro .got</span><br></pre></td></tr></table></figure>
<p>上面包含了ELF Header，所有Program Header以及Section Header的信息，最后还指明了每个section会整合进哪一个segment中，可以看到数据段应该是第2个segment。</p>
<h1 id="进程的创建与程序加载"><a href="#进程的创建与程序加载" class="headerlink" title="进程的创建与程序加载"></a>进程的创建与程序加载</h1><h2 id="整体视图"><a href="#整体视图" class="headerlink" title="整体视图"></a>整体视图</h2><p>在shell终端输入.&#x2F;parent，shell进程会调用fork()和execve()来创建新进程并加载.&#x2F;parent文件映像到父进程空间，然后parent进程又会同样调用fork()和execve()来创建新进程并加载.&#x2F;child文件映像到子进程空间。</p>
<div style = "align: center">
<img src="https://note.youdao.com/yws/api/personal/file/WEB680b0b8f4b6098490039e8f6a025de95?method=download&shareKey=69113f8f61e335d1864757cf6d288929" width="40%" height="40%"/> 

<h2 id="Fork系统调用"><a href="#Fork系统调用" class="headerlink" title="Fork系统调用"></a>Fork系统调用</h2><p>fork函数的原型是$\verb+pid_t fork(void)+$，返回值有3种：子进程pid、0、-1。如果fork失败，那么返回-1。为了让父进程知道自己创建的子进程号，fork会给父进程返回子进程的pid，并且没有pid为0的的进程，因此fork给子进程返回0，通过返回值将父子进程区分开。调用fork之后，子进程会完全拷贝父进程的地址空间，因此两份进程的代码是一样的，只不过子进程是在fork系统调用才开始执行代码的，两者在$if$语句分道扬镳，就像一个叉子一样。<br>在Unix系统中提供了3种创建进程相关的系统调用: fork、vfork和clone，三种系统调用的区别如下：</p>
<table>
<thead>
<tr>
<th align="center">系统调用</th>
<th align="center">区别</th>
</tr>
</thead>
<tbody><tr>
<td align="center">fork</td>
<td align="center">无参数，子进程是父进程完整拷贝：复制父进程所有资源包括地址空间(mm_struct:包含指向页目录表和页表的指针)、页表、打开文件表、信号处理等，新版内核增加了写时复制COW，fork的代价仅剩拷贝父进程页表</td>
</tr>
<tr>
<td align="center">vfork</td>
<td align="center">无参数，父子进程共享地址空间：同一个mm_struct，无需复制，子进程完全运行在父进程的地址空间上，因此子进程修改变量，父进程的变量也会改变。为防止父进程重写子进程需要的数据，阻塞父进程执行，直到子进程退出或者使用exec加载新的程序</td>
</tr>
<tr>
<td align="center">clone</td>
<td align="center">有参数，父进程的资源有选择性的拷贝给子进程：clone_flags参数共享哪些资源，其余资源进行复制</td>
</tr>
</tbody></table>
<p>在调用fork系统调用时，创建的新任务具有父进程的所有相关数据的副本，更高版本的内核增加了写时复制(Copy On Write)，父子进程共享一组资源，例如数据段，设置为只读，如果子进程修改了数据段中的变量，数据段中的内容拷贝到新的内存中再进行修改，因此子进程对变量修改不会影响父进程。调用clone系统调用时，创建的新任务并不具有所有数据的拷贝，clone_flags参数决定共享哪些资源，例如$\verb+CLONE_VM+$决定共享相同的内存空间，$\verb+CLONE_FILES+$决定共享相同的打开文件。如果不设置这些参数，那么clone与fork功能类似。在内核中三种函数的执行流程如下：</p>
<div style = "align: center">
<img src="https://note.youdao.com/yws/api/personal/file/WEBc958d4e5ba53bf36d8f1c91908b8483c?method=download&shareKey=69113f8f61e335d1864757cf6d288929" width="40%" height="40%"/>  

<ul>
<li>注：在Linux中fork()利用clone()来实现，在C程序中调用fork()函数会触发120号系统调用clone，不会触发2号系统调用fork！我猜应该是Linux中采用了写时复制技术，很多资源父子进程共享，所以不用全部拷贝，部份拷贝，其余资源共享即可，所以用clone系统调用。（以上过程在i386-32位平台上实现）</li>
</ul>
<p>因此，parent.c程序中执行fork和execve系统调用时，数据段中的str1字符串发生的改变如下：<br>1、刚进入main函数，父进程指向str1所在物理页面，且页面可写；</p>
<div style="align: center">
<img src="https://note.youdao.com/yws/api/personal/file/WEB220b71cadf3b1b5bac4278836e4a0316?method=download&shareKey=69113f8f61e335d1864757cf6d288929" width="70%" height="70%"/>  

<p>2、fork()函数执行后，父子进程共同指向str1物理页面，且页面只读；</p>
<div style="align: center">
<img src="https://note.youdao.com/yws/api/personal/file/WEB3721974e0a188301cfda36c6af2c619f?method=download&shareKey=69113f8f61e335d1864757cf6d288929" width="70%" height="70%"/>  

<p>3、子进程试图修改str1的内容，发生写时复制，str1拷贝到新内存区域防止篡改父进程数据；</p>
<div style="align: center">
<img src="https://note.youdao.com/yws/api/personal/file/WEB57c257d4ead121d8bc11a07729ae3391?method=download&shareKey=69113f8f61e335d1864757cf6d288929" width="70%" height="70%"/> 

<p>4、执行execve后子进程的mm_struct以及页目录项、页表项全部改变；</p>
<div style="align: center">
<img src="https://note.youdao.com/yws/api/personal/file/WEBbf788e3c7683fe13a889e12fcb327420?method=download&shareKey=69113f8f61e335d1864757cf6d288929" width="70%" height="70%"/> 

<p>如果将C程序中的fork()改为vfork()，则父子进程的mm_struct、页目录和页表项均共享，可以直接篡改对方进程的数据：</p>
<div style="align: center">
<img src="https://note.youdao.com/yws/api/personal/file/WEBeba8d4cdae87b5cff22f3f2d04def660?method=download&shareKey=69113f8f61e335d1864757cf6d288929" width="70%" height="70%"/> 

<h2 id="Execve系统调用"><a href="#Execve系统调用" class="headerlink" title="Execve系统调用"></a>Execve系统调用</h2><p>execve()函数是exec函数家族的一员，exec函数簇的6个函数功能类似，差别在于程序变量的表示方式和是否传入环境变量。exec会将可执行文件的绝对路径作为参数，把当前正在运行的用户的进程体（代码段、数据段、堆、栈、）用该可执行文件的进程体替换。<br>在shell终端输入一个可执行程序的文件名，shell程序会先用fork系统调用创建子进程，然后再调用execve系统调用，利用新的可执行文件的进程体替换fork出来的子进程的进程体，从而实现新进程执行完全不一样的新程序。<br>execve函数定义如下</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span> <span class="title">execve</span><span class="params">(<span class="type">const</span> <span class="type">char</span> *filename, <span class="type">char</span> *<span class="type">const</span> argv[], <span class="type">char</span> *<span class="type">const</span> envp[])</span></span>;</span><br></pre></td></tr></table></figure>
<p>三个参数分别是是可执行文件名、命令行参数和环境变量。execve()函数执行的主要轨迹如下：</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">execve</span>()</span><br><span class="line">&#123;</span><br><span class="line">    <span class="built_in">sys_execve</span>()</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="built_in">do_execve</span>()</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="built_in">do_execveat_common</span>()                        <span class="comment">//完成struct linux_binprm bprm初始化</span></span><br><span class="line">            &#123;</span><br><span class="line">                <span class="built_in">load_elf_binary</span>()</span><br><span class="line">                &#123;</span><br><span class="line">                    <span class="built_in">load_elf_phdrs</span>();                   <span class="comment">//读取所有的程序头</span></span><br><span class="line">                    <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>; i &lt; e_phnum; i++)</span><br><span class="line">                    &#123;</span><br><span class="line">                        <span class="keyword">if</span> (e_type != PT_LOAD) <span class="keyword">continue</span>;</span><br><span class="line">                        <span class="built_in">elf_map</span>();            <span class="comment">//mmap代码段和数据段，并建立用户进程到文件页高速缓存</span></span><br><span class="line">                    &#125;                         <span class="comment">//的映射关系，同时创建vm_area_struct</span></span><br><span class="line">                    <span class="built_in">start_thread</span>()</span><br><span class="line">                    &#123;</span><br><span class="line">                        regs-&gt;ip = new_ip;              <span class="comment">//入口地址设置为elf header中的e_entry</span></span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;        </span><br></pre></td></tr></table></figure>
<p>exec函数簇的6个函数最终都会执行execve()系统调用，在sys_execve()服务例程中，do_execve()函数调用do_execveat_common()来完成结构体$\verb+struct linux_binprm bprm+$的初始化，用来记录可执行文件的信息。该函数还会调用path_look_up()和dentry_open()获得可执行文件相关的目录项对象、文件对象和inode对象（《深入理解Linux内核》），执行完该函数后，进入load_elf_binary()函数之前，$\verb+struct linux_binprm bprm+$中的内容如下所示：</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  buf = <span class="string">&quot;\177ELF\001\001\001\003\000\000\000\000\000\000\000\000\002\000\003\000\001</span></span><br><span class="line"><span class="string">  \000\000\000\n\215\004\b4\000\000\000\f4\n\000\000\000\000\000\064\000 \000\006\000</span></span><br><span class="line"><span class="string">  (\000$\000!\000\001\000\000\000\000\000\000\000\000\200\004\b\000\200\004\bo\000\n</span></span><br><span class="line"><span class="string">  \000o\000\n\000\005\000\000\000\000\020\000\000\001\000\000\000X\017\n\000X\237\016</span></span><br><span class="line"><span class="string">  \bX\237\016\bH\000\000\314\063\000\000\006\000\000\000\000\020\000\000\004\000\000</span></span><br><span class="line"><span class="string">  \000\364\000\000\000\364\200\004\b&quot;</span>, vma = <span class="number">0xc011c528</span>,</span><br><span class="line">  vma_pages = <span class="number">2</span>, mm = <span class="number">0xc5cc7a40</span>, p = <span class="number">3221225460</span>, cred_prepared = <span class="number">1</span>,</span><br><span class="line">  cap_effective = <span class="number">1</span>, recursion_depth = <span class="number">1</span>, file = <span class="number">0xc7542300</span>,</span><br><span class="line">  cred = <span class="number">0xc6393640</span>, unsafe = <span class="number">0</span>, per_clear = <span class="number">0</span>, argc = <span class="number">0</span>, envc = <span class="number">0</span>,</span><br><span class="line">  filename = <span class="number">0xc75353d0</span> <span class="string">&quot;./child&quot;</span>, interp = <span class="number">0xc75353d0</span> <span class="string">&quot;./child&quot;</span>,</span><br><span class="line">  interp_flags = <span class="number">0</span>, interp_data = <span class="number">0</span>, loader = <span class="number">0</span>, exec = <span class="number">3221225460</span>&#125;</span><br></pre></td></tr></table></figure>
<p>其中buf为128字节，这些字节包含的是ELF文件格式的魔数和其他信息（即ELF Header），用八进制表示，可以看到开头的’\177ELF’就是前面说到的ELF Header的开头几个魔数。并且此时的vma(vm_area_Struct)只有栈段，mm(mm_struct)已经分配好了但是还没有初始化，将来会用新的mm替换当前的mm并且将会创建数据段和代码段的vm来插入当前的vma链表。会在接下来的load_elf_binary()函数中完成该过程。<br>此时内存的情况如下所示：</p>
<div style="align: center">
<img src="https://note.youdao.com/yws/api/personal/file/WEBa0ad675812fc28302e56120229572181?method=download&shareKey=69113f8f61e335d1864757cf6d288929" width="70%" height="70%"/> 

<p>load_elf_binary()函数为可执行文件的接口，执行的过程如下：</p>
<ul>
<li><p>1、动态创建一个结构体：</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"> <span class="keyword">struct</span> </span><br><span class="line"> &#123;</span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">elfhdr</span> elf_ex;</span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">elfhdr</span> interp_elf_ex;</span><br><span class="line"> &#125; *loc;</span><br></pre></td></tr></table></figure>
<p>然后从传入参数的bprm-&gt;buf中获得elf header的信息，并进行校验：魔数必须匹配，程序的类型必须为ET_EXEC或者ET_DYN，检查bprm-&gt;file-&gt;f_op-&gt;mmap，指向的文件是否已经映射到内存中；</p>
</li>
<li><p>2、查找解释器段<br>遍历所有程序头（一共6个），通过遍历每个段，找到PT_INTERP类型段，也即是解释器段，找到说明需要运行过程中的动态链接。“解释器”段实际上只是一个字符串，即解释器的文件名，最终记录在elf_interpreter变量中。另外child程序是静态编译的程序，不需要动态链接，也就没有解析器段。</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">elf_phdata = <span class="built_in">load_elf_phdrs</span>(&amp;loc-&gt;elf_ex, bprm-&gt;file);</span><br><span class="line">elf_ppnt = elf_phdata;</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (i = <span class="number">0</span>; i &lt; loc-&gt;elf_ex.e_phnum; i++) </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">if</span> (elf_ppnt-&gt;p_type == PT_INTERP) </span><br><span class="line">      &#123;</span><br><span class="line">          ...</span><br><span class="line">	elf_interpreter = <span class="built_in">kmalloc</span>(elf_ppnt-&gt;p_filesz, GFP_KERNEL);</span><br><span class="line">          <span class="comment">//根据其位置的p_offset和大小p_filesz把整个&quot;解释器&quot;段的内容读入缓冲区</span></span><br><span class="line">	<span class="built_in">kernel_read</span>(bprm-&gt;file, elf_ppnt-&gt;p_offset, elf_interpreter,elf_ppnt-&gt;p_filesz);</span><br><span class="line">          <span class="comment">//struct *file类型的interpreter指针指向解释器段</span></span><br><span class="line">	interpreter = <span class="built_in">open_exec</span>(elf_interpreter);</span><br><span class="line">          <span class="comment">//读入其开头的128个字节，即解释器文件的elf头部。</span></span><br><span class="line">          <span class="built_in">kernel_read</span>(interpreter, <span class="number">0</span>, (<span class="type">void</span>*)&amp;loc-&gt;interp_elf_ex, <span class="built_in">sizeof</span>(loc-&gt;interp_elf_ex));</span><br><span class="line">          ...</span><br><span class="line">	<span class="keyword">break</span>;</span><br><span class="line">&#125;</span><br><span class="line">elf_ppnt++;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
<li><p>3、清除前一个计算的所有资源，并分配新资源</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">flush_old_exec</span>(bprm);</span><br><span class="line">...</span><br><span class="line"><span class="built_in">setup_new_exec</span>(bprm);</span><br></pre></td></tr></table></figure>
</li>
<li><p>4、设置栈段<br>检查所有的程序段，如果某一个段的类型为PT_GNU_STACK，即栈段，那么检查标志并设定相应的值，然后调用setup_arg_pages()函数利用do_execve()生成的参数页面的信息，来设定本程序$\verb+struct linux_binprm bprm+$的栈顶地址，然后mm-&gt;start_stack &#x3D; bprm-&gt;p,将mm的栈的起始地址设定为bprm中栈顶指针指向的位置。</p>
</li>
</ul>
<p>跳过中间一些处理器相关的检查操作，直接来到ELF段载入阶段</p>
<ul>
<li><p>5、加载目标程序必须的段，即将ELF文件中的映像载入内存。</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span>(i = <span class="number">0</span>, elf_ppnt = elf_phdata; i &lt; loc-&gt;elf_ex.e_phnum; i++, elf_ppnt++) </span><br><span class="line">  &#123;</span><br><span class="line"><span class="type">int</span> elf_prot = <span class="number">0</span>, elf_flags;</span><br><span class="line"><span class="type">unsigned</span> <span class="type">long</span> k, vaddr;</span><br><span class="line"><span class="type">unsigned</span> <span class="type">long</span> total_size = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">      <span class="comment">//搜索PT_LOAD段，也就是需要加载的段，只有代码段和数据段需要装入</span></span><br><span class="line"><span class="keyword">if</span> (elf_ppnt-&gt;p_type != PT_LOAD)</span><br><span class="line">	<span class="keyword">continue</span>;</span><br><span class="line"></span><br><span class="line">      <span class="comment">//检查标志、页面信息</span></span><br><span class="line"><span class="keyword">if</span> (elf_ppnt-&gt;p_flags &amp; PF_R) elf_prot |= PROT_READ;</span><br><span class="line"><span class="keyword">if</span> (elf_ppnt-&gt;p_flags &amp; PF_W) elf_prot |= PROT_WRITE;</span><br><span class="line"><span class="keyword">if</span> (elf_ppnt-&gt;p_flags &amp; PF_X) elf_prot |= PROT_EXEC;</span><br><span class="line"></span><br><span class="line">vaddr = elf_ppnt-&gt;p_vaddr;</span><br><span class="line"></span><br><span class="line">      <span class="comment">//设置e_flags标志</span></span><br><span class="line">      <span class="comment">//...</span></span><br><span class="line">      total_size = <span class="built_in">total_mapping_size</span>(elf_phdata, loc-&gt;elf_ex.e_phnum);</span><br><span class="line"></span><br><span class="line">      <span class="comment">//通过elf_map()来将用户虚拟地址load + vaddr和文件映像中的区域映射</span></span><br><span class="line"><span class="built_in">elf_map</span>(bprm-&gt;file, load_bias + vaddr, elf_ppnt, elf_prot, elf_flags, total_size);</span><br><span class="line">  &#125;</span><br></pre></td></tr></table></figure>
<p>遍历所有段，如果该段是可加载段（child程序的可加载段就是代码段和数据段），就确定装入内存的地址load_bias + vaddr，并通过elf_map()来建立用户虚拟地址和文件映像中的区域映射。这里的load_bias是随机生成的偏移量，在映射到进程的虚拟地址空间时，栈、堆、解析器段的起始地址往往加上一个随机偏移量。因为整个程序的虚拟起始地址固定为0x08048000，敏感的栈区域容易被算出地址，被黑客利用。elf_map利用vm_map来建立虚拟地址到文件映像的映射，与mmap类似。<br>mmap会将文件从交换空间加载进内存，并为进程新创建一个vm_area_struct，同时建立vm_area_struct与进程段的映射关系，例如代码段的vm_area_struct的vm_start字段表明代码起始地址为0x08048000，vm_end字段表明代码段的结束位置。现在代码段和数据段已经加载到内存中了。并且代码段和数据段的vm_area_struct也已经设置好了，插入了进程的mmap指向的vma链表中：</p>
<div style="align: center">
<img src="https://note.youdao.com/yws/api/personal/file/WEBa5e38da11d4ff698e0aa0010fc73d156?method=download&shareKey=69113f8f61e335d1864757cf6d288929" width="70%" height="70%"/> 
</li>
<li><p>6、接下来是填写程序的入口地址。</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"> <span class="keyword">if</span> (elf_interpreter) </span><br><span class="line"> &#123;</span><br><span class="line"><span class="type">unsigned</span> <span class="type">long</span> interp_map_addr = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">elf_entry = <span class="built_in">load_elf_interp</span>(&amp;loc-&gt;interp_elf_ex, interpreter, </span><br><span class="line">               &amp;interp_map_addr, load_bias, interp_elf_phdata);</span><br><span class="line"> &#125; </span><br><span class="line"> <span class="keyword">else</span> </span><br><span class="line"> &#123;</span><br><span class="line">elf_entry = loc-&gt;elf_ex.e_entry;</span><br><span class="line"> &#125;</span><br></pre></td></tr></table></figure>
<p>如果存在解释器段，就通过load_elf_interp()将其映像装入内存, 并把将来进入用户空间的入口地址elf_entry设置成解释器映像的入口地址，这样返回用户空间时先执行解析器程序，将需要的共享库(shared lib)映射到进程的虚拟地址空间中。如果没有解释器段，也就是child程序的情况，那么直接从ELF Header的e_entry字段获得程序入口地址（child文件映像的入口地址）。<br>此时入口地址应该是0x08048d0a!</p>
</li>
<li><p>7、执行前的准备<br>首先调用create_elf_tables()函数填写目标文件的命令行参数、环境变量等信息。这些信息需要复制到用户空间，使它们在PC跳转到解释器或目标映像的程序入口地址时出现在用户空间堆栈上。</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">create_elf_tables</span>(bprm, &amp;loc-&gt;elf_ex, load_addr, interp_load_addr);</span><br></pre></td></tr></table></figure>
<p>vm_area_struct线性区结构体的映射由mmap完成，现在完成mm_struct的初始化。</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"> current-&gt;mm-&gt;end_code = end_code;</span><br><span class="line"> current-&gt;mm-&gt;start_code = start_code;</span><br><span class="line"> current-&gt;mm-&gt;start_data = start_data;</span><br><span class="line"> current-&gt;mm-&gt;end_data = end_data;</span><br><span class="line"> current-&gt;mm-&gt;start_stack = bprm-&gt;p;</span><br><span class="line"> <span class="keyword">if</span> ((current-&gt;flags &amp; PF_RANDOMIZE) &amp;&amp; (randomize_va_space &gt; <span class="number">1</span>)) </span><br><span class="line"> &#123;</span><br><span class="line">current-&gt;mm-&gt;brk = current-&gt;mm-&gt;start_brk = <span class="built_in">arch_randomize_brk</span>(current-&gt;mm);</span><br><span class="line"> &#125;</span><br></pre></td></tr></table></figure></li>
<li><p>8、调用start_thread()函数准备执行此ELF程序<br>该函数是一个与体系结构相关的函数，在i386中其核心函数如下：</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">regs-&gt;fs = <span class="number">0</span>;</span><br><span class="line">regs-&gt;ds = __USER_DS;</span><br><span class="line">regs-&gt;es = __USER_DS;</span><br><span class="line">regs-&gt;ss = __USER_DS;</span><br><span class="line">regs-&gt;cs = __USER_CS;</span><br><span class="line">regs-&gt;ip = new_ip;</span><br><span class="line">regs-&gt;sp = new_sp;</span><br><span class="line">regs-&gt;flags = X86_EFLAGS_IF;</span><br></pre></td></tr></table></figure>
<p>最后，函数跳转到regs-&gt;ip处(地址0x8048d0a)执行，execve系统调用结束。</p>
</li>
</ul>
<p>最终内存的情况如下图所示：</p>
<div style="align: center">
<img src="https://note.youdao.com/yws/api/personal/file/WEBaa532b54422051cd4217f2017b02d9ec?method=download&shareKey=69113f8f61e335d1864757cf6d288929" width="70%" height="70%"/> 

<p>至此，程序的创建和可执行文件的加载过程全部结束！</p>

      
    </div>
    <footer class="article-footer">
      <a data-url="https://chudod.gitee.io/myworks/2022/05/06/OS_ELF_execve/" data-id="cl3kznr04000jj0ukaltm27l5" data-title="Linux程序执行与进程创建" class="article-share-link">Share</a>
      
      
      
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/myworks/tags/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/" rel="tag">操作系统</a></li></ul>

    </footer>
  </div>
  
</article>



  
    <article id="post-Triggered_Operation" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/myworks/2022/04/28/Triggered_Operation/" class="article-date">
  <time class="dt-published" datetime="2022-04-27T16:00:00.000Z" itemprop="datePublished">2022-04-28</time>
</a>
    
  <div class="article-category">
    <a class="article-category-link" href="/myworks/categories/%E5%B9%B6%E8%A1%8C%E8%AE%A1%E7%AE%97/">并行计算</a>►<a class="article-category-link" href="/myworks/categories/%E5%B9%B6%E8%A1%8C%E8%AE%A1%E7%AE%97/In-Network-Collectives/">In-Network Collectives</a>
  </div>

  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="p-name article-title" href="/myworks/2022/04/28/Triggered_Operation/">使用触发操作卸载集合通信</a>
    </h1>
  

      </header>
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h1 id="Introduction"><a href="#Introduction" class="headerlink" title="Introduction"></a>Introduction</h1><p>天河的互连网络接口中设计了一种基于触发的通信卸载机制，集合通信操作卸载到互连网络中自主触发执行。互连网络中设计的计算逻辑部件，可以支持归约操作中的各种计算操作，从而将集合通信操作完全卸载(offload)到网络中。事实上，基于触发操作(Triggered Operation)的通信卸载机制还有可编程网络接口$\verb+API-Protals 4.0+$，富士通推出的片上互连系统$\verb+Tofu-2+$（结点之间采用控制报文触发进行集合通信操作的卸载，与天河互连网络通信卸载实现机制很相似），以及$\verb+Myrinet+$等等（补充中）。通过$\verb+Google+$上论文的引用关系，我发现最早提出触发机制的是$\verb+Portals 4+$，于2010年提出，寻根之旅了属于是。</p>
<h1 id="寻根之旅：Protals-4"><a href="#寻根之旅：Protals-4" class="headerlink" title="寻根之旅：Protals 4"></a>寻根之旅：Protals 4</h1><p>最早利用触发机制实现集合通信卸载的工作是$\verb+Portals 4+$上为$\verb+MPI_Allreduce+$操作设计的，于2010年发表在<a target="_blank" rel="noopener" href="https://ieeexplore.ieee.org/abstract/document/6041532">Enabling Flexible Collective Communication Offload with Triggered Operations</a>上:”This paper presents triggered operations — a semantic building block that allows the key components of collective communications to be offloaded while allowing the host side software to define the algorithm”。$\verb+Portals 4+$设计了一个语义模块，包含触发操作(Trigger Operation)和计数事件机制(Counting events)。当计数事件到达了一个特定的阈值时，应用程序就会调度一个指定的网络操作。并且利用$\verb+Portals 4+$定义的触发函数重新实现了$\verb+Tree Algorithm+$和$\verb+Recursive Doubling+$。随后$\verb+Portals 4+$又为$\verb+Barrier+$和$\verb+Broadcast+$设计了触发操作算法（<a target="_blank" rel="noopener" href="https://link.springer.com/chapter/10.1007/978-3-642-15646-5_26">原文链接</a>）。触发操作在语义上功能强大，并且能够提高性能。</p>
<div style="align: center">
<img src="https://note.youdao.com/yws/api/personal/file/WEBca6784a6d45e7df074c9c9aa2673e557?method=download&shareKey=6655e070e6950d853516df65854d5ecf" width="70%" height="70%"/>  

<h1 id="片上互连系统：Tofu-2"><a href="#片上互连系统：Tofu-2" class="headerlink" title="片上互连系统：Tofu-2"></a>片上互连系统：Tofu-2</h1>
      
    </div>
    <footer class="article-footer">
      <a data-url="https://chudod.gitee.io/myworks/2022/04/28/Triggered_Operation/" data-id="cl3kznr0d001dj0uka51vgkjp" data-title="使用触发操作卸载集合通信" class="article-share-link">Share</a>
      
      
      
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/myworks/tags/%E5%B9%B6%E8%A1%8C%E8%AE%A1%E7%AE%97/" rel="tag">并行计算</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/myworks/tags/%E9%9B%86%E5%90%88%E9%80%9A%E4%BF%A1/" rel="tag">集合通信</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/myworks/tags/%E9%AB%98%E6%80%A7%E8%83%BD%E8%AE%A1%E7%AE%97/" rel="tag">高性能计算</a></li></ul>

    </footer>
  </div>
  
</article>



  
    <article id="post-Topology_Aware_Collectives" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/myworks/2022/04/25/Topology_Aware_Collectives/" class="article-date">
  <time class="dt-published" datetime="2022-04-24T16:00:00.000Z" itemprop="datePublished">2022-04-25</time>
</a>
    
  <div class="article-category">
    <a class="article-category-link" href="/myworks/categories/%E5%B9%B6%E8%A1%8C%E8%AE%A1%E7%AE%97/">并行计算</a>►<a class="article-category-link" href="/myworks/categories/%E5%B9%B6%E8%A1%8C%E8%AE%A1%E7%AE%97/Topology-Aware-Algorithms/">Topology-Aware Algorithms</a>
  </div>

  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="p-name article-title" href="/myworks/2022/04/25/Topology_Aware_Collectives/">高性能互连网络与拓扑感知算法</a>
    </h1>
  

      </header>
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h1 id="Abstract"><a href="#Abstract" class="headerlink" title="Abstract"></a>Abstract</h1><p>拓扑感知(Topology-Aware)的集合通信算法是近些年兴起的一个研究方向，顾名思义，就是将MPI的集合通信算法部署到高性能计算网络上，来充分发挥网络的性能，并且针对不同网络的拓扑结构和协议特点来设计不同的集合通信算法。这一页面列举了最近时髦的一些HPC网络以及对应的拓扑感知算法。在Top 500排行榜中的计算机系统通常采用的网络拓扑结构有Fattree、Torus、Dragonfly，目前，前几名没有用到Dragonfly。</p>
<h1 id="Gragonfly网络"><a href="#Gragonfly网络" class="headerlink" title="Gragonfly网络"></a>Gragonfly网络</h1><h2 id="Introduction"><a href="#Introduction" class="headerlink" title="Introduction"></a>Introduction</h2><p>Gragonfly（蜻蜓）网络是最近非常时髦的一种HPC网络，在2008年提出：<a target="_blank" rel="noopener" href="https://dl-acm-org-s.nudtproxy.yitlink.com/doi/10.1145/1394608.1382129">Technology-Driven, Highly-Scalable Dragonfly Topology</a>。其优点是高度的可伸缩性(high scalability)，低网络直径(low diameter)、成本低(low cost)等等。目前许多HPC系统都使用了Dragonfly网络拓扑。<br>下图是一个9组路由器72个终端节点的Dragonfly网络的例子（图片来源:<a target="_blank" rel="noopener" href="https://ieeexplore-ieee-org-s.nudtproxy.yitlink.com/document/9644896">文献链接</a>）。</p>
<div style="align: center">
<img src="https://note.youdao.com/yws/api/personal/file/WEBc0e3f19d5bb9c51887b22cf2f8c218ba?method=download&shareKey=4561f9353c0edc6f6b5daa810174cdbe" width="40%" height="40%"/>   

<p>Dragonfly网络分成Group层、System层这两层：</p>
<ul>
<li>Group层：一个Group内一共$a$个交换机（或路由器），$a$个交换机都是全连接的，一个交换机连接着$p$个计算节点，上图中一个路由器连接两个计算节点。上图中的$9$个虚线框代表着$9$个Group层，每个Group层有$4$个全连接的路由器。</li>
<li>System层：一共有$g$个Group，每个Group视为一个虚拟的交换机，Group之间进行全连接，在图中就是$9$个Group进行全连接。组内的每个交换机与其他交换机的连接中，有$a-1$条链路连接到组内的交换机，还有$h&#x3D;\frac{g-1}{a}$条链路是与其他Group之中的交换机相连结。在上图中，每个路由器有$3$条线连接到组内的路由器，还有$2$条连接到了其他Group中的路由器。并且组内的链路(intra-group)的延迟比组间链路(inter-group)的延迟高不少。</li>
</ul>
<h2 id="网络属性与形式化表达"><a href="#网络属性与形式化表达" class="headerlink" title="网络属性与形式化表达"></a>网络属性与形式化表达</h2><p>Gragonfly网络可以用$DF(p,a,h,g)$来形式化表达，例如上图中的例子可以用$DF(p&#x3D;2,a&#x3D;4,h&#x3D;2,g&#x3D;9)$来表达。一个Gragonfly网络最佳的参数配置是：<br>$$a&#x3D;2p&#x3D;2h$$<br>因此可以得到如下的性质：</p>
<ul>
<li>每个交换机端口的数量为$p+h+(a-1)$</li>
<li>每个虚拟交换机（一个$Group$）中的外接端口数量为$ah$，整个网络的全局链路数为$\frac{a\cdot{h}\cdot{g}}{2}$</li>
<li>$Group$的数量为$g&#x3D;ah+1$（由前面的公式$h&#x3D;\frac{g-1}{a}$推导可得）</li>
<li>$DF(p,a,h,g)$网络中一共有$P&#x3D;p\cdot{a}\cdot{g}&#x3D;ap(ah+1)$个节点，因此$DF(n,2n,n,g)$这种最佳配置的网络中的计算节点的数量为$P&#x3D;2p^2(2p^2+1)$</li>
</ul>
<h2 id="Dragonfly网络的拓扑感知集合通信算法"><a href="#Dragonfly网络的拓扑感知集合通信算法" class="headerlink" title="Dragonfly网络的拓扑感知集合通信算法"></a>Dragonfly网络的拓扑感知集合通信算法</h2><p>Dragonfly网络上做集合通信算法的工作不多，论文只有寥寥几篇。最早的论文发表在$\verb+2012 EuroMPI+$上。这几篇论文设计的集合通信算法中，唯独没有$Allreduce$操作，所以我的师兄才抓住了这个点，在Dragonfly网络上设计$\verb+Allreduce+$算法，发了一篇$\verb+ISPA+$的会议论文，在我看来是非常好的想法了。</p>
<h3 id="Collectives-on-Two-Tier-Direct-Networks"><a href="#Collectives-on-Two-Tier-Direct-Networks" class="headerlink" title="Collectives on Two-Tier Direct Networks"></a><a target="_blank" rel="noopener" href="https://link.springer.com/chapter/10.1007/978-3-642-33518-1_12">Collectives on Two-Tier Direct Networks</a></h3><p>该工作在Dragonfly以及IBM PERCS这两个双层的网络上对常规的集合通信操作（包括$\verb+Scatter Gather Allgather Broadcast Reduce-Scatter Reduce+$这6中操作）针对网络拓扑的特点设计了拓扑感知算法。其思想主要是利用了局部链路(Local Link)比全局链路(Global Link)快很多得特点，而且算法设计得比较简单，优化空间很多。</p>
<h1 id="Bcube网络"><a href="#Bcube网络" class="headerlink" title="Bcube网络"></a>Bcube网络</h1><p>Bcube网络拓扑的结构如下所示：</p>
<div style="align: center">
<img src="https://note.youdao.com/yws/api/personal/file/WEB5d657aab3c672d03c9ff7dc7b7ac1527?method=download&shareKey=4561f9353c0edc6f6b5daa810174cdbe" width="60%" height="60%"/>   

<p>用$Bcube(n,k)$来形式化的表达$Bcube$网络，$n$表示网络中的每个交换机都有$n$个端口，连接到$n$个不同的主机（$n$一般取$2<del>32$），$k$表示每个主机都有$k$个网卡来连接到$k$个不同的交换机（$k$一般取$2</del>4$）。交换机一共有$k$层，所以每个主机的$k$个网卡分别连接到$0, 1, …, k-1$层的交换机。并且主机和主机之间没有直接的链路连接，必须通过交换机连接。下图所表示的就是一个$Bcube(3,2)$的网络（图片来源：<a target="_blank" rel="noopener" href="https://proceedings.neurips.cc/paper/2018/file/f410588e48dc83f2822a880a68f78923-Paper.pdf">BML</a>）。</p>
<div style="align: center">
<img src="https://note.youdao.com/yws/api/personal/file/WEBedc750c2ece3d90077374a411436e990?method=download&shareKey=4561f9353c0edc6f6b5daa810174cdbe" width="60%" height="60%"/>   

<p>目前，在Bcube上做集合通信算法设计和优化的工作很少，即便有少数几篇相关的，也是在Bcube上做分布式机器学习参数同步算法的研究。由于参数同步操作与$\verb+Allreduce+$操作高度相似，因此在Bcube上设计参数同步算法也就相当于做$\verb+Allreduce+$算法。<br><a target="_blank" rel="noopener" href="https://proceedings.neurips.cc/paper/2018/file/f410588e48dc83f2822a880a68f78923-Paper.pdf">BML:A High-performance, Low-cost Gradient Synchronization Algorithm for DML Training</a>是第一个在Bcube上做分布式机器学习参数同步算法的工作，其实该参数同步算法并不复杂，本质上就是一个$\verb+Reduce+$ + $\verb+Broadcast+$的组合，如下图所示:</p>
<div style="align: center">
<img src="https://note.youdao.com/yws/api/personal/file/WEB7e70f458806199ea4992bf8eb594660b?method=download&shareKey=4561f9353c0edc6f6b5daa810174cdbe" width="60%" height="60%"/>  

<h1 id="Torus网络"><a href="#Torus网络" class="headerlink" title="Torus网络"></a>Torus网络</h1><p>Torus的英文直译就是环面的意思，在每一维都将该维度坐标相同的计算节点组织成一个绕接的环，图中展示的是一个二维的Torus网络。</p>
<div style="align: center">
<img src="https://note.youdao.com/yws/api/personal/file/WEBbaccac337aea7e37f3f4df12205d3db2?method=download&shareKey=4561f9353c0edc6f6b5daa810174cdbe" width="30%" height="30%"/> 

<h1 id="Dcell网络"><a href="#Dcell网络" class="headerlink" title="Dcell网络"></a>Dcell网络</h1><p>Dceil的拓扑结构看起来和Dragonfly网络非常相似。</p>
<div style="align: center">
<img src="https://note.youdao.com/yws/api/personal/file/WEB4a9b8282c017c3476aa98370093376a7?method=download&shareKey=4561f9353c0edc6f6b5daa810174cdbe" width="40%" height="40%"/> 
      
    </div>
    <footer class="article-footer">
      <a data-url="https://chudod.gitee.io/myworks/2022/04/25/Topology_Aware_Collectives/" data-id="cl3kznr0s003mj0ukasmpd03f" data-title="高性能互连网络与拓扑感知算法" class="article-share-link">Share</a>
      
      
      
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/myworks/tags/Topology-Aware/" rel="tag">Topology-Aware</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/myworks/tags/%E5%B9%B6%E8%A1%8C%E8%AE%A1%E7%AE%97/" rel="tag">并行计算</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/myworks/tags/%E9%9B%86%E5%90%88%E9%80%9A%E4%BF%A1/" rel="tag">集合通信</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/myworks/tags/%E9%AB%98%E6%80%A7%E8%83%BD%E8%AE%A1%E7%AE%97/" rel="tag">高性能计算</a></li></ul>

    </footer>
  </div>
  
</article>



  
    <article id="post-TorstenHeofler" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/myworks/2022/04/20/TorstenHeofler/" class="article-date">
  <time class="dt-published" datetime="2022-04-19T16:00:00.000Z" itemprop="datePublished">2022-04-20</time>
</a>
    
  <div class="article-category">
    <a class="article-category-link" href="/myworks/categories/%E7%A1%AC%E6%A0%B8%E7%8B%A0%E4%BA%BA/">硬核狠人</a>
  </div>

  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="p-name article-title" href="/myworks/2022/04/20/TorstenHeofler/">硬核狠人之Torsten Heofler</a>
    </h1>
  

      </header>
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        
      
    </div>
    <footer class="article-footer">
      <a data-url="https://chudod.gitee.io/myworks/2022/04/20/TorstenHeofler/" data-id="cl3kznr0c0018j0ukfzfsevj3" data-title="硬核狠人之Torsten Heofler" class="article-share-link">Share</a>
      
      
      
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/myworks/tags/%E7%A1%AC%E6%A0%B8%E7%8B%A0%E4%BA%BA/" rel="tag">硬核狠人</a></li></ul>

    </footer>
  </div>
  
</article>



  
    <article id="post-OS_Memory_Management" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/myworks/2022/04/14/OS_Memory_Management/" class="article-date">
  <time class="dt-published" datetime="2022-04-13T16:00:00.000Z" itemprop="datePublished">2022-04-14</time>
</a>
    
  <div class="article-category">
    <a class="article-category-link" href="/myworks/categories/%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/">计算机基础知识</a>►<a class="article-category-link" href="/myworks/categories/%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/">操作系统</a>
  </div>

  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="p-name article-title" href="/myworks/2022/04/14/OS_Memory_Management/">操作系统内存管理</a>
    </h1>
  

      </header>
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h1 id="一、分页系统"><a href="#一、分页系统" class="headerlink" title="一、分页系统"></a>一、分页系统</h1><h2 id="1、段页式系统"><a href="#1、段页式系统" class="headerlink" title="1、段页式系统"></a>1、段页式系统</h2><p>段页式内存管理的模型中，逻辑地址（虚拟地址）先根据分段系统转换成线性地址，然后线性地址在分页系统中查询，Linux中弱化了分段机制，只在80x86处理器中使用分段。$Linux$采用了4级分页模型来适应多种硬件环境，但在80x86处理器中（IA-32架构）中使用二级分页模型，即页目录表和页表结合，将第2、3级页表整合进了页全局目录中。在64位体系结构中，2级页表不再适用，因此IA-64体系结构采用了3级页表，64位地址中39位（9+9+9+12）来寻址。</p>
<div style="align: center">
<img src="https://note.youdao.com/yws/api/personal/file/WEB0d12a226c3f38c1f969af829e12275af?method=download&shareKey=69113f8f61e335d1864757cf6d288929" width="60%" height="60%"/>  
<div style="align: center">
<img src="https://note.youdao.com/yws/api/personal/file/WEB93d72c4515da95343499f2207f959eb8?method=download&shareKey=69113f8f61e335d1864757cf6d288929" width="60%" height="60%"/>  

<h2 id="2、自己做的页目录表和页表"><a href="#2、自己做的页目录表和页表" class="headerlink" title="2、自己做的页目录表和页表"></a>2、自己做的页目录表和页表</h2><p>这是我本科做实验时自己做的页目录和页表。其中用户程序使用$\verb+0x00<del>0xcfffffff+$这3GB逻辑地址空间，系统程序使用$\verb+0xc0000000</del>0xffffffff+$这1GB逻辑地址空间。在物理内存中，$\verb+0x00<del>0xfffff+$这1MB空间留给BIOS、MBR、Loader、中断向量表，页目录表位于内存$\verb+0x100000</del>0x100fff+$，大小共1KB，含1024个页目录项。页表紧跟着页目录表后面，页表0的地址为$\verb+0x101000<del>0x101fff+$，页表1的地址为$\verb+0x102000</del>0x102fff+$，依次类推。<br>页目录表中的第$\verb+0<del>767+$页目录项映射到低3GB逻辑内存中，而第$\verb+768</del>1022+$页目录项映射到高1GB逻辑内存中，1023号页目录项指向页目录表自己，而768号页目录项指向页表0，769号页目录项指向页表1，以此类推。页表0的第一个页表项指向地址$\verb+0x00+$为起始的4KB物理页（最上面的物理页0）。</p>
<div style="align: center">
<img src="https://note.youdao.com/yws/api/personal/file/WEBaa4e07bd5ea8a36a7fee1b719e45e1e8?method=download&shareKey=69113f8f61e335d1864757cf6d288929" width="60%" height="60%"/>

<p>注意所有用户的页目录表的$\verb+768<del>1022+$项完全相同，因为都指向共享的内核空间。创建进程时从页目录表的第$\verb+768</del>1022+$拷贝即可（图片中写错字了，应该是页目录表而不是页表）。</p>
<div style="align: center">
<img src="https://note.youdao.com/yws/api/personal/file/WEBeef4de30e9a491b8e5e67f7ac6a28611?method=download&shareKey=69113f8f61e335d1864757cf6d288929" width="60%" height="60%"/>

<h1 id="二、Linux内存管理"><a href="#二、Linux内存管理" class="headerlink" title="二、Linux内存管理"></a>二、Linux内存管理</h1><p>这里以一个用户程序$\verb+abc.c+$为例来探究Linux系统的内存管理策略。程序如下：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;string.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;stdlib.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="type">char</span> bar[<span class="number">3968</span>]=<span class="string">&quot;\n&quot;</span>;</span><br><span class="line"><span class="type">char</span> foo[<span class="number">4096</span>]=<span class="string">&quot;this is not a test\n&quot;</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">void</span> <span class="title function_">output_loop</span><span class="params">(<span class="type">char</span> * str)</span></span><br><span class="line">&#123;</span><br><span class="line">  <span class="type">int</span> i;</span><br><span class="line">  <span class="keyword">for</span>(i=<span class="number">0</span>; i&lt;<span class="number">20</span>; i++)&#123;</span><br><span class="line">    write(<span class="number">2</span>, str, <span class="built_in">strlen</span>(str));</span><br><span class="line">    sched_yield();</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="type">void</span> <span class="title function_">main</span><span class="params">()</span>&#123;</span><br><span class="line">  <span class="type">int</span> pid1, pid2, status;</span><br><span class="line"></span><br><span class="line">  write(<span class="number">2</span>, foo, <span class="built_in">strlen</span>(foo));</span><br><span class="line">  <span class="built_in">strcpy</span>(foo, <span class="string">&quot;you are modified\n&quot;</span>);</span><br><span class="line">  write(<span class="number">2</span>, foo, <span class="built_in">strlen</span>(foo));</span><br><span class="line">    </span><br><span class="line">  <span class="keyword">if</span> (!(pid1 = fork()))&#123;</span><br><span class="line">    output_loop(<span class="string">&quot;B  &quot;</span>);</span><br><span class="line">    <span class="built_in">exit</span>(<span class="number">0</span>);</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span> (!(pid2 = fork()))&#123;</span><br><span class="line">    output_loop(<span class="string">&quot;C  &quot;</span>);</span><br><span class="line">    <span class="built_in">exit</span>(<span class="number">0</span>);</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  output_loop(<span class="string">&quot;A  &quot;</span>);</span><br><span class="line">  waitpid(pid1, &amp;status, <span class="number">0</span>);</span><br><span class="line">  waitpid(pid2, &amp;status, <span class="number">0</span>);</span><br><span class="line">  write(<span class="number">2</span>, <span class="string">&quot;\n&quot;</span>, <span class="number">1</span>);</span><br><span class="line"></span><br><span class="line">  <span class="keyword">while</span>(<span class="number">1</span>);</span><br><span class="line"></span><br><span class="line">  <span class="built_in">exit</span>(<span class="number">0</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h2 id="1、进程地址空间"><a href="#1、进程地址空间" class="headerlink" title="1、进程地址空间"></a>1、进程地址空间</h2><p>abc程序的逻辑地址空间（右侧）如下图所示。其中用户程序使用$\verb+0x00-0xcfffffff+$这3GB逻辑地址空间，$\verb+abc+$程序的代码段为$\verb+0x08048000-0x080e8fff+$这161个页面，代码段为$\verb+0x080e9000-0x080ecfff+$这4个页面。数据段只包含$bar$和$foo$这两个变量对应的字符串，$bar$的地址为$\verb+0x080e9000+$，虽然只有3968个字节，但是也分配了2个页面（4096个字节），占用数据段中的第0、1个页面，$foo$的地址为$\verb+0x080eb000+$，占用数据段中的第2、3个页面。$\verb+task_struct+$为Linux的进程控制块PCB，里面包含指向内存控制块$\verb+mm_struct+$（所有内核进程的$\verb+mm_struct+$全部内容均为0）的指针。$\verb+mm_struct+$包含指向页目录表的指针$\verb+pgd+$以及指向$\verb+vm_area_struct+$线性区结构的指针$\verb+mmap+$，结构体$\verb+vm_area_struct+$描述的对应逻辑段的起始和结束逻辑地址等信息。所有$\verb+vm_area_struct+$组织成一棵红黑树。<br><img src="https://note.youdao.com/yws/api/personal/file/WEB4e818deadc690a92531ae4b7dd59f4f9?method=download&shareKey=69113f8f61e335d1864757cf6d288929" alt="Linux分页系统以及abc程序的地址空间"><br>$foo$字符串的逻辑地址为$\verb+0x080eb000+$，高10位$\verb+0x20+$表示从页目录表的第$\verb+0x20+$项（对应的偏移为$\verb+0x80+$，一个页表项4个字节）取出页表地址，注意该处的$\verb+0x07518067+$的低12位为标志，不表示地址，页表的单位为4KB，故页表地址的低12位总是0。然后从$foo$字符串的中间10位$\verb+0xeb+$对应的偏移$\verb+0x3ac+$从页表中取出页帧的起始地址$\verb+0x065c6000+$，最后与$foo$字符串低12位页内偏移$\verb+0x000+$直接相加就可以得到$foo$字符串的物理地址。</p>
<h2 id="2、Linux的页描述符和页高速缓存"><a href="#2、Linux的页描述符和页高速缓存" class="headerlink" title="2、Linux的页描述符和页高速缓存"></a>2、Linux的页描述符和页高速缓存</h2><p>内存中的一个页称为页帧($page\ frame$)，一个页帧对应一个32字节的页描述符$\verb+struct page+$来描述，页帧描述符数组$\verb+struct page mem_map[]+$来描述所有的页帧，占整个内存空间的$\frac{32}{4096}&#x3D;\frac{1}{128}$。<br>为了更快速的读取文件，Linux在$\verb+abc+$程序刚开始运行时，数据段还没有被访问前就已经把文件中的数据段缓存入了内存中，但是页目录表和页表并没有内容指向这部分缓存，Linux只会在访问数据段中的变量时才会分配页目录项和页表项（这也叫做“请求调页”），缓存的页框称为页高速缓存。页高速缓存的每一个页框对应一个页描述符，页描述符用基树组织起来，如下图所示。</p>
<div style="align: center">
<img src="https://note.youdao.com/yws/api/personal/file/WEB2ba0e77ad04bc1d9cac6fbc86f2116b9?method=download&shareKey=69113f8f61e335d1864757cf6d288929" width="60%" height="60%"/>

<p>本例中$\verb+abc+$程序的基树如下图所示：<br><img src="https://note.youdao.com/yws/api/personal/file/WEB16b4d85145c8837036c4a41d3cfcc745?method=download&shareKey=69113f8f61e335d1864757cf6d288929"><br>图中数据段的页描述符的偏移为$\verb+0xa0+$，应该位于第2个基树叶子节点的第32个槽，该槽中的指针指向对应的$\verb+struct page+$，再指向对应的页帧缓存。  </p>
<h1 id="三、Linux缺页处理"><a href="#三、Linux缺页处理" class="headerlink" title="三、Linux缺页处理"></a>三、Linux缺页处理</h1><h2 id="1、缺页处理流程"><a href="#1、缺页处理流程" class="headerlink" title="1、缺页处理流程"></a>1、缺页处理流程</h2><p>这里以$\verb+abc+$程序中的三个函数来分析缺页处理。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">write(<span class="number">2</span>, foo, <span class="built_in">strlen</span>(foo));</span><br><span class="line"><span class="built_in">strcpy</span>(foo, <span class="string">&quot;you are modified\n&quot;</span>);</span><br><span class="line">write(<span class="number">2</span>, foo, <span class="built_in">strlen</span>(foo));</span><br></pre></td></tr></table></figure>
<h3 id="执行第一个write系统调用"><a href="#执行第一个write系统调用" class="headerlink" title="执行第一个write系统调用"></a>执行第一个write系统调用</h3><p>数据段包含$\verb+bar+$和$\verb+foo+$字符串，$\verb+foo+$字符串的起始地址为$\verb+0x080eb000+$，占2个页帧。程序执行到$\verb+write+$函数前一刻，数据段作为页高速缓存，缓存在了内存中，但是页目录项和页表项均为0，没有指向这个页缓存。程序在内核态往虚拟地址0x080ecf20(数据段第4页)写内容，（我也不知道写的是什么内容，可能是初始化的信息），发现页目录项为0。<br><img src="https://note.youdao.com/yws/api/personal/file/WEB71a5c80affeec83e41ff2c5e05c29bbd?method=download&shareKey=69113f8f61e335d1864757cf6d288929" alt="第一次缺页时的初始状态"><br>此时引发缺页异常，执行$\verb+__do_page_fault+$缺页处理函数，执行$\verb+do_cow_fault+$写时复制，修改页目录项，但页表项仍然全0，再从$\verb+0x065c9000+$拷贝数据到另一片内存$\verb+0x01b35000+$中，并修改第4个页表项为$\verb+0x01b35067+$(最低位为7表示该页面可写)，指向拷贝的内存。最后回到引发缺页的指令，重启该指令往逻辑地址$\verb+0x080e9fc4+$（也就是物理地址$\verb+0x01b35000+$处）写内容。<br>注意，页表项不能直接指向页缓存$\verb+0x065d1000+$处并向该地址写内容，必须先拷贝内容到另一块内存中，否则页缓存$\verb+0x065d1000+$成为脏页面，脏页面的内容会写回磁盘中，从而引起磁盘上程序内容的改变。<br><img src="https://note.youdao.com/yws/api/personal/file/WEBc26ad4fdc414d7430d64c730752ee683?method=download&shareKey=69113f8f61e335d1864757cf6d288929" alt="第一次缺页处理"><br>然后程序在用户态往$\verb+0x080e9fc4+$(数据段第1页)写内容，发现页帧不存在，开始缺页处理，执行$\verb+do_cow_fault+$函数，从$\verb+0x065c6000+$拷贝数据到另一片内存中$\verb+0x01b34000+$，并修改第一个页表项指向拷贝的内存。<br><img src="https://note.youdao.com/yws/api/personal/file/WEB66fe4e1cdb31a275d66e865d022732bf?method=download&shareKey=69113f8f61e335d1864757cf6d288929" alt="第二次缺页处理"><br>随后是第3次缺页异常，在用户态往$\verb+0x80ea040+$(数据段第2页)读内容，发现页帧不存在，引发缺页处理，执行$\verb+do_read_fault+$函数，因为只是读该页面，不需要写页面，所以修改第2、3个页表项指向第2、3个页帧缓存$\verb+0x065cf000+$和$\verb+0x065d0000+$即可，页表项的最低4位为5表示该页面只读。<br><img src="https://note.youdao.com/yws/api/personal/file/WEB8faa3a5ed4916f2e7e69871238033cff?method=download&shareKey=69113f8f61e335d1864757cf6d288929"><br>之后是第4次缺页异常，程序在用户态往$\verb+0x80ea040+$(数据段第2页)写内容，发现该页面只读，执行$\verb+do_wp_page+$函数，从第2个页表项指向的$\verb+0x065cf000+$拷贝内容到新的内存地址$\verb+0x07d85000+$并修改页表项指向拷贝的新页帧。我发现程序往这个地址写的竟然是空字符串””。<br><img src="https://note.youdao.com/yws/api/personal/file/WEB5c7b6dc7cb9a07568443d4d5a5bb82a9?method=download&shareKey=69113f8f61e335d1864757cf6d288929"><br>此时程序刚刚进入$main$函数，然后终端打印$\verb+foo+$字符串，$\verb+write+$结束。全局的视角看起来应该是这样：<br><img src="https://note.youdao.com/yws/api/personal/file/WEB26fa4947c1e7e03f31b54dddae8be1a9?method=download&shareKey=69113f8f61e335d1864757cf6d288929"></p>
<h3 id="执行strcpy函数"><a href="#执行strcpy函数" class="headerlink" title="执行strcpy函数"></a>执行strcpy函数</h3><p>$\verb+strcpy+$函数将$\verb+foo+$字符串的内容改写成”you are modified.”。此时$\verb+foo+$字符串所在的地址为第3个页表项指向的页面缓存。在用户态往$\verb+0x80eb000+$(第3页，即foo字符串地址)写内容，发现该页面只读，执行$\verb+do_wp_page+$函数，从第3个页表项指向的$\verb+foo+$字符串地址$\verb+0x065d0000+$拷贝字符串到内存$0x01b3a000$处并修改页表项指向新拷贝的内存地址，再往新的页帧写字符串$\verb+”you are modified”+$。<br><img src="https://note.youdao.com/yws/api/personal/file/WEB3f2c9510c2c066da94bf25f657684598?method=download&shareKey=69113f8f61e335d1864757cf6d288929"><br>$\verb+strcpy+$函数结束时4个页表项都将最低为从7改为5，此时页面只读，不可写，然后$\verb+strcpy+$结束，执行$\verb+write+$函数，打印新的字符串。<br><img src="https://note.youdao.com/yws/api/personal/file/WEBe288d6203e8207ba7782b958abb5ffbe?method=download&shareKey=69113f8f61e335d1864757cf6d288929"></p>
<h2 id="2、回写脏页面"><a href="#2、回写脏页面" class="headerlink" title="2、回写脏页面"></a>2、回写脏页面</h2><p>若在执行$\verb+strcpy+$函数之前，把第3个页表项标志位改为7结尾，页面变为可写，在执行$\verb+strcpy+$函数时，新字符串的将会被写入第3个页表项指向的$\verb+foo+$字符串地址$\verb+0x065d0000+$中，该页帧成为脏页面，回写到磁盘上，磁盘上的程序内容也会被更改，下次执行abc程序时直接输出新字符串。<br><img src="https://note.youdao.com/yws/api/personal/file/WEBd1510963910d7d4323be7e44608a5c7b?method=download&shareKey=69113f8f61e335d1864757cf6d288929"><br>下次执行程序时的结果：<br><img src="https://note.youdao.com/yws/api/personal/file/WEB3a05bb03ae842bdefed44e3e9abd9af8?method=download&shareKey=69113f8f61e335d1864757cf6d288929"><br>两次打印的都是修改后的字符串。</p>

      
    </div>
    <footer class="article-footer">
      <a data-url="https://chudod.gitee.io/myworks/2022/04/14/OS_Memory_Management/" data-id="cl3kznr06000qj0ukf4o3h8h7" data-title="操作系统内存管理" class="article-share-link">Share</a>
      
      
      
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/myworks/tags/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/" rel="tag">操作系统</a></li></ul>

    </footer>
  </div>
  
</article>



  


  <nav id="page-nav">
    
    <span class="page-number current">1</span><a class="page-number" href="/myworks/page/2/">2</a><a class="page-number" href="/myworks/page/3/">3</a><a class="extend next" rel="next" href="/myworks/page/2/">Next &raquo;</a>
  </nav>

</section>
        
          <aside id="sidebar">
  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Categories</h3>
    <div class="widget">
      <ul class="category-list"><li class="category-list-item"><a class="category-list-link" href="/myworks/categories/English/">English</a></li><li class="category-list-item"><a class="category-list-link" href="/myworks/categories/%D0%A0%D0%BE%D1%81%D1%81%D0%B8%D1%8F/">Россия</a></li><li class="category-list-item"><a class="category-list-link" href="/myworks/categories/%E5%AF%BC%E8%88%AA/">导航</a></li><li class="category-list-item"><a class="category-list-link" href="/myworks/categories/%E5%B9%B6%E8%A1%8C%E8%AE%A1%E7%AE%97/">并行计算</a><ul class="category-list-child"><li class="category-list-item"><a class="category-list-link" href="/myworks/categories/%E5%B9%B6%E8%A1%8C%E8%AE%A1%E7%AE%97/In-Network-Collectives/">In-Network Collectives</a></li><li class="category-list-item"><a class="category-list-link" href="/myworks/categories/%E5%B9%B6%E8%A1%8C%E8%AE%A1%E7%AE%97/MPI%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1/">MPI程序设计</a></li><li class="category-list-item"><a class="category-list-link" href="/myworks/categories/%E5%B9%B6%E8%A1%8C%E8%AE%A1%E7%AE%97/MPI%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1%E4%B8%8E%E5%B9%B6%E8%A1%8C%E7%AE%97%E6%B3%95/">MPI程序设计与并行算法</a></li><li class="category-list-item"><a class="category-list-link" href="/myworks/categories/%E5%B9%B6%E8%A1%8C%E8%AE%A1%E7%AE%97/MPI%E8%BD%AF%E4%BB%B6%E6%A0%88%E8%AE%BE%E8%AE%A1/">MPI软件栈设计</a></li><li class="category-list-item"><a class="category-list-link" href="/myworks/categories/%E5%B9%B6%E8%A1%8C%E8%AE%A1%E7%AE%97/MPI%E9%9B%86%E5%90%88%E9%80%9A%E4%BF%A1%E7%AE%97%E6%B3%95/">MPI集合通信算法</a></li><li class="category-list-item"><a class="category-list-link" href="/myworks/categories/%E5%B9%B6%E8%A1%8C%E8%AE%A1%E7%AE%97/Topology-Aware-Algorithms/">Topology-Aware Algorithms</a></li></ul></li><li class="category-list-item"><a class="category-list-link" href="/myworks/categories/%E6%95%B4%E6%B4%BB%E7%B3%BB%E5%88%97/">整活系列</a></li><li class="category-list-item"><a class="category-list-link" href="/myworks/categories/%E7%A1%AC%E6%A0%B8%E7%8B%A0%E4%BA%BA/">硬核狠人</a></li><li class="category-list-item"><a class="category-list-link" href="/myworks/categories/%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/">计算机基础知识</a><ul class="category-list-child"><li class="category-list-item"><a class="category-list-link" href="/myworks/categories/%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/">操作系统</a></li></ul></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Tags</h3>
    <div class="widget">
      <ul class="tag-list" itemprop="keywords"><li class="tag-list-item"><a class="tag-list-link" href="/myworks/tags/English-Vocabulary/" rel="tag">English Vocabulary</a></li><li class="tag-list-item"><a class="tag-list-link" href="/myworks/tags/English-Writing/" rel="tag">English Writing</a></li><li class="tag-list-item"><a class="tag-list-link" href="/myworks/tags/MPI/" rel="tag">MPI</a></li><li class="tag-list-item"><a class="tag-list-link" href="/myworks/tags/Topology-Aware/" rel="tag">Topology-Aware</a></li><li class="tag-list-item"><a class="tag-list-link" href="/myworks/tags/%D0%A0%D0%BE%D1%81%D1%81%D0%B8%D1%8F/" rel="tag">Россия</a></li><li class="tag-list-item"><a class="tag-list-link" href="/myworks/tags/%E5%9C%A8%E7%BD%91%E8%AE%A1%E7%AE%97/" rel="tag">在网计算</a></li><li class="tag-list-item"><a class="tag-list-link" href="/myworks/tags/%E5%B9%B6%E8%A1%8C%E7%AE%97%E6%B3%95/" rel="tag">并行算法</a></li><li class="tag-list-item"><a class="tag-list-link" href="/myworks/tags/%E5%B9%B6%E8%A1%8C%E8%AE%A1%E7%AE%97/" rel="tag">并行计算</a></li><li class="tag-list-item"><a class="tag-list-link" href="/myworks/tags/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/" rel="tag">操作系统</a></li><li class="tag-list-item"><a class="tag-list-link" href="/myworks/tags/%E6%95%B4%E6%B4%BB/" rel="tag">整活</a></li><li class="tag-list-item"><a class="tag-list-link" href="/myworks/tags/%E7%94%9F%E6%B4%BB/" rel="tag">生活</a></li><li class="tag-list-item"><a class="tag-list-link" href="/myworks/tags/%E7%A1%AC%E6%A0%B8%E7%8B%A0%E4%BA%BA/" rel="tag">硬核狠人</a></li><li class="tag-list-item"><a class="tag-list-link" href="/myworks/tags/%E9%9B%86%E5%90%88%E9%80%9A%E4%BF%A1/" rel="tag">集合通信</a></li><li class="tag-list-item"><a class="tag-list-link" href="/myworks/tags/%E9%AB%98%E6%80%A7%E8%83%BD%E8%AE%A1%E7%AE%97/" rel="tag">高性能计算</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Tag Cloud</h3>
    <div class="widget tagcloud">
      <a href="/myworks/tags/English-Vocabulary/" style="font-size: 10px;">English Vocabulary</a> <a href="/myworks/tags/English-Writing/" style="font-size: 10px;">English Writing</a> <a href="/myworks/tags/MPI/" style="font-size: 17.5px;">MPI</a> <a href="/myworks/tags/Topology-Aware/" style="font-size: 10px;">Topology-Aware</a> <a href="/myworks/tags/%D0%A0%D0%BE%D1%81%D1%81%D0%B8%D1%8F/" style="font-size: 12.5px;">Россия</a> <a href="/myworks/tags/%E5%9C%A8%E7%BD%91%E8%AE%A1%E7%AE%97/" style="font-size: 12.5px;">在网计算</a> <a href="/myworks/tags/%E5%B9%B6%E8%A1%8C%E7%AE%97%E6%B3%95/" style="font-size: 10px;">并行算法</a> <a href="/myworks/tags/%E5%B9%B6%E8%A1%8C%E8%AE%A1%E7%AE%97/" style="font-size: 20px;">并行计算</a> <a href="/myworks/tags/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/" style="font-size: 15px;">操作系统</a> <a href="/myworks/tags/%E6%95%B4%E6%B4%BB/" style="font-size: 10px;">整活</a> <a href="/myworks/tags/%E7%94%9F%E6%B4%BB/" style="font-size: 10px;">生活</a> <a href="/myworks/tags/%E7%A1%AC%E6%A0%B8%E7%8B%A0%E4%BA%BA/" style="font-size: 10px;">硬核狠人</a> <a href="/myworks/tags/%E9%9B%86%E5%90%88%E9%80%9A%E4%BF%A1/" style="font-size: 15px;">集合通信</a> <a href="/myworks/tags/%E9%AB%98%E6%80%A7%E8%83%BD%E8%AE%A1%E7%AE%97/" style="font-size: 12.5px;">高性能计算</a>
    </div>
  </div>

  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Archives</h3>
    <div class="widget">
      <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/myworks/archives/2022/05/">May 2022</a></li><li class="archive-list-item"><a class="archive-list-link" href="/myworks/archives/2022/04/">April 2022</a></li><li class="archive-list-item"><a class="archive-list-link" href="/myworks/archives/2022/03/">March 2022</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Recent Posts</h3>
    <div class="widget">
      <ul>
        
          <li>
            <a href="/myworks/2022/05/24/Russian_Grammar/">Русская Граммаатика(俄语语法)</a>
          </li>
        
          <li>
            <a href="/myworks/2022/05/18/OS_FileSystem/">文件系统概念和Ext2文件系统</a>
          </li>
        
          <li>
            <a href="/myworks/2022/05/14/English_Sentences/">English Sentences</a>
          </li>
        
          <li>
            <a href="/myworks/2022/05/11/English_Vocabulary/">English Vocabulary</a>
          </li>
        
          <li>
            <a href="/myworks/2022/05/11/Russian_Vocabulary/">Русские Слова(俄语单词)</a>
          </li>
        
      </ul>
    </div>
  </div>

  
</aside>
        
      </div>
      <footer id="footer">
  
  <div class="outer">
    <div id="footer-info" class="inner">
      
      &copy; 2022 John Doe<br>
      Powered by <a href="https://hexo.io/" target="_blank">Hexo</a>
    </div>
  </div>
</footer>

    </div>
    <nav id="mobile-nav">
  
    <a href="/myworks/" class="mobile-nav-link">Home</a>
  
    <a href="/myworks/archives" class="mobile-nav-link">Archives</a>
  
</nav>
    


<script src="/myworks/js/jquery-3.4.1.min.js"></script>



  
<script src="/myworks/fancybox/jquery.fancybox.min.js"></script>




<script src="/myworks/js/script.js"></script>





  </div>
</body>
</html>